js的Promise

js发生异步的情况

1、定时器都是异步操作

2、事件绑定都是异步操作

3、AJAX中一般我们都采取异步操作(也可以同步)

4、回调函数可以理解为异步(不是严谨的异步操作)

剩下的做同步处理

 

Promise详解

参考连接: https://www.runoob.com/w3cnote/javascript-promise-object.html

Promise的三种状态

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态

一旦状态改变,就不会再变,任何时候都可以得到这个结果

Promise 对象的状态改变,只有两种可能

1.从 Pending 变为 Resolved

2.从 Pending 变为 Rejected

只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果

pending:

初始状态,不是成功或失败状态

fulfilled:

意味着操作成功完成。

rejected:

意味着操作失败。

 

Promise优缺点

优点

可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数

Promise 对象提供统一的接口,使得控制异步操作更加容易

允许将回调函数的横向加载改成纵向加载,详见下方:使用案例:横向加载变为纵向

Promise 的最大问题是代码冗余,一眼看去都是一堆 then,语义变得很不清楚。

缺点

无法取消 Promise,一旦新建它就会立即执行,无法中途取消

如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部

 

Promise使用案例

入门案例
var myFirstPromise = new Promise(function(resolve, reject){
    //当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...)
    //在本例中,我们使用setTimeout(...)来模拟异步代码,实际编码时可能是XHR请求或是HTML5的一些API方法.
    setTimeout(function(){
        resolve("成功!"); //代码正常执行!
    }, 250);
});
 
myFirstPromise.then(function(successMessage){
    //successMessage的值是上面调用resolve(...)方法传入的值.
    //successMessage参数不一定非要是字符串类型,这里只是举个例子
    document.write("Yay! " + successMessage);
});

  

改变Promise状态案例

resolve 方法和 reject 方法调用时,都带有参数

它们的参数会被传递给回调函数

reject 方法的参数通常是 Error 对象的实例

而 resolve 方法的参数除了正常的值以外,还可能是另一个 Promise 实例

function ajax(URL) {
    return new Promise(function (resolve, reject) {
        var req = new XMLHttpRequest(); 
        req.open('GET', URL, true);
        req.onload = function () {
        if (req.status === 200) { 
                // 变为Resolved状态,用onFulfilled接收,意味着操作成功完成
                resolve(req.responseText);
            } else {
                // 变为Rejected状态,用onRejected接收,意味着操作失败
                reject(new Error(req.statusText));
            } 
        };
        req.onerror = function () {
            // 变为Resolved状态,用onFulfilled接收,意味着操作成功完成
            reject(new Error(req.statusText));
        };
        req.send(); 
    });
}
var URL = "/try/ajax/testpromise.php"; 
ajax(URL).then(function onFulfilled(value){
    document.write('内容是:' + value); 
}).catch(function onRejected(error){
    document.write('错误:' + error); 
});
​
​
​
// -------------------------------------------
​
// resolve 的参数为 另一个 Promise 案例
var p1 = new Promise(function(resolve, reject){
  // ... some code
});
 
var p2 = new Promise(function(resolve, reject){
  // ... some code
  resolve(p1);
})

  

Promise.prototype.then链式操作

依次指定了两个回调函数

第一个回调函数完成以后,会将返回结果作为参数传入第二个回调函数

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // 对comments进行处理
});

  

Promise.prototype.catch

Promise.prototype.catch 方法是 Promise.prototype.then(null, rejection) 的别名

用于指定发生错误时的回调函数

Promise 对象的错误具有"冒泡"性质会一直向后传递,直到被捕获为止

也就是说,错误总是会被下一个 catch 语句捕获

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // some code
}).catch(function(error) {
  // 处理前两个回调函数的错误
});

  

横向加载变为纵向
// 如果依次读取多个文件,就会出现多重嵌套。代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理
fs.readFile(fileA, function (err, data) {
  fs.readFile(fileB, function (err, data) {
    // ...
  });
});
​
​
// -----------------------------------
​
// Promise 的写法只是回调函数的改进,使用then方法以后,异步任务的两段执行看得更清楚了
var readFile = require('fs-readfile-promise');
​
readFile(fileA)
.then(function(data){
  console.log(data.toString());
})
.then(function(){
  return readFile(fileB);
})
.then(function(data){
  console.log(data.toString());
})
.catch(function(err) {
  console.log(err);
});
 

  

 

posted @ 2020-12-21 14:40  minnersun  阅读(117)  评论(0编辑  收藏  举报