我所理解的Promise

场景1:多个接口异步请求数据,需要通过前一个接口的返回值来决定后一个接口如何处理。我们一般会把第二个请求放到第一个请求执行成功的回调函数里面:

$.ajax({
    url: '/data/a',
    success: function (data) {
        $.ajax({
            // 第一个请求完成后执行第二次请求
            url: '/data/b',
            success: function (data) {
                 // ......
            }
        });
    }
});

场景2:需要从多个接口获取数据(接口之间无先后顺序),重新组织好数据后渲染到页面。

像上面这种解决办法并没有哪里不对,只是当多几个接口的时候,嵌套的层次就会很深,不便于后期的阅读。
而且如果是场景2也像这么写,又会导致一个一个接口去请求数据,效率降低了。

那么,有什么好的解决方案呢。除开从数据上入手以外,那就是今天的主角Promise。

什么是Promise

Promise是抽象异步处理对象以及对其进行各种操作的组件。我们可以把Promise对象当成一次将要执行的操作,多个操作之间用链式调用来完成。

Promise状态

  • pending: 初始状态。
  • resolved: 成功的操作。
  • rejected: 失败的操作。

Promise状态

Promise兼容性

Promise兼容性

目前为止主流浏览器新版本都能够支持,第三方库里面也有大部分已经实现。

resolve和reject方法

resolve使Promise对象的状态改变成成功,并将成功参数传递到后续的成功处理操作。
reject使Promise对象的状态改变成失败,并将失败参数传递到后续的失败处理操作。

function mockAjax(flag) {
    return new Promise(function (resolve, reject) {
        if (flag) {
            resolve("right");
        } else {
            reject("error");
        }
    });
}

//成功操作
function done(msg){
    console.log(msg);
}

//失败操作
function fail(msg){
    console.log(msg);
}

mockAjax(true).then(done, fail);

Promise.then()接受两个参数,成功和失败的操作。

catch

如上面demo的操作,我们把then后面的操作延长,我们一般来说只关心成功后的操作;对于失败的操作,可能都是千篇一律的处理,我们就可以使用catch,就像是java中捕获异常一样。

mockAjax(false)
    .then(done)
    .then(done)
    .then(done)
    .catch(fail);

这里我们通过《javascript Promise迷你书》当中的一幅图来说明Promise的执行过程:

promise
    .then(taskA)
    .then(taskB)
    .catch(onRejected)
    .then(finalTask);

Promise执行过程

Promise.all

通过前面的操作,已经能够很好的解决场景1的问题,但是场景2并没有很好的解决。

所以,Promise提供了all方法,Promise.all接受一个数组,只有数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用后面的.then方法。

他还有一个好基友就是Promise.race,其特点就是只要有一个promise对象变成resolve或reject状态,他就会继续后面的操作。

应用

刚开始接触这玩意儿,应用不是很多,主要是在用到jQuery的ajax的时候用到

var _done = function(data){
    //成功处理
},
_fail = function(){
    //失败处理
};

var xhr = $.ajax({
    url: "/data/xxx",
    type: 'GET',
    data: ""
});
xhr.done(_done).fail(_fail);

参考资料

更多内容,请阅读JavaScript Promise迷你书