ES6 之 promise

promise 是一步变成的一种解决方案,比传统的回调函数和事件更强大和合理, es6将其写入语言标准,统一了用法,并原生提供了 promise对象.从语法上来说, promise 是一个对象,从它可以获取异步操作的消息, promise 提供统一的 api, 各种异步操作都可以用同样的方法进行处理.

promise 的特点

对象的状态不受外界影响

promise 对象代表一个异步操作,有三种状态, pending(进行中),fulfilled(已成功)和 rejected(已失败).只有结果来决定当前是哪种状态.

一旦状态改变就不再变化

promise 对象的改变,只有两种可能,从 pending 变为 fulfilled 和从 pending 变为 rejected, 发生这两种状态改变以后装填就不再变化了.如果改变已经发生了,再对 promise 对象添加回调函数,也会立即得到这个结果.

基本用法

promise 对象是一个构造函数,用来生成 promise 实例.

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

Promise 构造函数接受一个函数作为参数,该函数的两个参数分别为 resolve 和 reject, 这两个参数是两个函数.

resolve 函数的作用是,将 promise 对象的状态从未完成装变为完成,即从 pending 变为 resolved. 在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;

reject 函数的作用是,将 promise 对象的状态从未完成变为失败,即从 pending 变为 rejected. 在异步操作失败时调用,并将异步操作爆出的信息,作为参数传递出去.

Promise 实例生成以后,可以使用 .then 方法来接收两个回调函数作为参数,第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。

也可以使用 .catch 来接收 promise 变为 rejected 时的回调函数.

function test(resolve, reject) {
    var timeOut = Math.random() * 2;
    log('set timeout to: ' + timeOut + ' seconds.');
    setTimeout(function () {
        if (timeOut < 1) {
            log('call resolve()...');
            resolve('200 OK');
        }
        else {
            log('call reject()...');
            reject('timeout in ' + timeOut + ' seconds.');
        }
    }, timeOut * 1000);
};
new Promise(test).then(function (result) {
    console.log('成功:' + result);
}).catch(function (reason) {
    console.log('失败:' + reason);
});

test()只关心自身的逻辑,并不关心具体的 resolve 和 rejected 将如何处理结果.也就是说 Promise 最大的好处,就是在异步执行的过程中,吧执行代码和处理结果清晰地分离了.

Promise还可以做更多的事情,比如,有若干个异步任务,需要先做任务1,如果成功后再做任务2,任何任务失败则不再继续并执行错误处理函数。

有些时候,多个异步任务是为了容错。比如,同时向两个URL读取用户的个人信息,只需要获得先返回的结果即可。这种情况下,用Promise.race()实现:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
Promise.race([p1, p2]).then(function (result) {
    console.log(result); // 'P1'
});

由于p1执行较快,Promise的then()将获得结果’P1’。p2仍在继续执行,但执行结果将被丢弃。

如果我们组合使用Promise,就可以把很多异步任务以并行和串行的方式组合起来执行。

to be continued…

thank u !