你不知道的JavaScript(中卷)|Promise(三)

Promise API 概述


new Promise(..) 构造器
有启示性的构造器Promise(..) 必须和new 一起使用,并且必须提供一个函数回调。这个回调是同步的或立即调用的。这个函数接受两个函数回调,用以支持promise 的决议。通常我们把这两个函数称为resolve(..) 和reject(..):

var p = new Promise(function(resolve, reject) {
    // resolve(..)用于决议/完成这个promise
    // reject(..)用于拒绝这个promise
});

reject(..) 就是拒绝这个promise;但resolve(..) 既可能完成promise,也可能拒绝,要根据传入参数而定。如果传给resolve(..) 的是一个非Promise、非thenable 的立即值,这个promise 就会用这个值完成。
但是,如果传给resolve(..) 的是一个真正的Promise 或thenable 值,这个值就会被递归展开,并且(要构造的)promise 将取用其最终决议值或状态。

Promise.resolve(..) 和Promise.reject(..)
创建一个已被拒绝的Promise 的快捷方式是使用Promise.reject(..),所以以下两个promise 是等价的:

var p1 = new Promise(function(resolve, reject) {
    reject("Oops");
});
var p2 = Promise.reject("Oops");

Promise.resolve(..) 常用于创建一个已完成的Promise,使用方式与Promise.reject(..)类似。但是,Promise.resolve(..) 也会展开thenable 值(前面已多次介绍)。在这种情况下,返回的Promise 采用传入的这个thenable 的最终决议值,可能是完成,也可能是拒绝:

var fulfilledTh = {
    then: function(cb) {
        cb(42);
    }
};
var rejectedTh = {
    then: function(cb, errCb) {
        errCb("Oops");
    }
};
var p1 = Promise.resolve(fulfilledTh);
var p2 = Promise.resolve(rejectedTh);
// p1是完成的promise
// p2是拒绝的promise

还要记住,如果传入的是真正的Promise,Promise.resolve(..) 什么都不会做,只会直接把这个值返回。所以,对你不了解属性的值调用Promise.resolve(..),如果它恰好是一个真正的Promise,是不会有额外的开销的。

then(..) 和catch(..)
每个Promise 实例(不是Promise API 命名空间)都有then(..) 和catch(..) 方法,通过这两个方法可以为这个Promise 注册完成和拒绝处理函数。Promise 决议之后,立即会调用这两个处理函数之一,但不会两个都调用,而且总是异步调用。
then(..) 接受一个或两个参数:第一个用于完成回调,第二个用于拒绝回调。如果两者中的任何一个被省略或者作为非函数值传入的话,就会替换为相应的默认回调。默认完成回调只是把消息传递下去,而默认拒绝回调则只是重新抛出(传播)其接收到的出错原因。

p.then( fulfilled );
p.then( fulfilled, rejected );
p.catch( rejected ); // 或者p.then( null, rejected )

Promise 局限性


顺序错误处理
Promise 的设计局限性(具体来说,就是它们链接的方式)造成了一个让人很容易中招的陷阱,即Promise 链中的错误很容易被无意中默默忽略掉。

单一值
根据定义,Promise 只能有一个完成值或一个拒绝理由。在简单的例子中,这不是什么问题,但是在更复杂的场景中,你可能就会发现这是一种局限了。
一般的建议是构造一个值封装(比如一个对象或数组)来保持这样的多个信息。这个解决方案可以起作用,但要在Promise 链中的每一步都进行封装和解封,就十分丑陋和笨重了。

其他promise知识点省略。

你可能感兴趣的:(你不知道的JavaScript(中卷)|Promise(三))