Promise学习笔记(三)

Promise的模式

Promise.all([…])

接收一个可迭代对象(数组/Map/Set),返回一个promise实例pAll。元素通常是promise实例,但也可以是一个thenable对象,也可以是一个立即值。

本质而言,列表中的每个值都会通过Promise.resolve(..)来过滤,以确保要等待的是一个真正的Promise实例

当且仅当这个可迭代对象中的所有promise实例都成功时,pAll才成功。

const p1 = new Promise((resolve, reject) => {
    resolve(1);
})
const p2 = new Promise((resolve, reject) => {
    resolve(2);
})

const pAll = Promise.all([p1,p2])

pAll.then(
    (values) => {
    	console.log('all resolved',values)
}, (reason) => {
    	console.log('reject',reason)
})
复制代码

如果pAll是成功的,就执行onResolved函数,其中values是一个数组,按照原来的先后顺序,存放promise的结果。

如果pAll是失败的,就执行onRejected函数,其中reason是第一个抛出的错误信息。

Promise.race()

这个模式叫竞态Promise。同样接收一个可迭代对象(数组/Map/Set),元素的类型可以是promise实例、thenable对象或立即值,并且返回一个promise实例pRace。

可迭代对象中第一个完成状态转换的promise,决定了pRace是成功还是失败:

(立即值在race中显然没什么意义,因为他一定是第一个resolve的)

const p1 = new Promise((resolve, reject) => {
    resolve(1);
})
const p2 = new Promise((resolve, reject) => {
    resolve(2);
})

const pRace = Promise.all([p1,p2]);

pRace.then(
    (res) => {
    	console.log('race resolved',res)
}, (reason) => {
    	console.log('race reject',reason)
}); 
复制代码

如果第一个完成状态转换的promise实例是成功的,就执行onResolved函数,输出的res是第一个成功的promise的结果。

如果第一个完成状态转换的promise实例是失败的,就执行onRejected函数,输出的reason是第一个失败的promise的结果。

Promise.finally()

返回一个promise,在上一个promise结束时,无论fulfilled还是rejected,都会执行指定的回调函数,可以避免同样的语句,在resolve和reject中各写一次的情况。

var p = Promise.resolve(42);

p.then(something).finally(cleanup);
复制代码

Promise的局限性

错误处理

前面也有提到Promise链中的错误很容易被无意中忽略掉。由于一个Promise链仅仅是连接到一起的成员Promise,而没有把整个链标识为一个实体,这意味着,没有外部的方法可以观察到可能发生的错误。

var p = foo(42).then(..).then(..);
复制代码

如上面一段代码,p指向的是最后一个then返回的promise,没有指定错误处理函数,如果出错了,在外部是没有办法获取到错误通知的。

单一值

Promise只能有一个完成值或一个拒绝理由。当我们想要传递多个参数的时候,我们将不得不使用一个对象或者数组传参。

但如果在Promise链中,每一步都这样封装和解封,就显得十分丑陋和笨重了。

Promise.resolve({
    foo: 'hello',
    bar: 'world',
}).then((value) => {
    const { foo, bar } = value;
    ...
});
复制代码

单决议

很多异步情况下,我们只会获取一个值一次,所以Promise只能被决议一次,不算是个缺点。

但对于异步的另一种模式,比如:按钮点击

var p = new Promise(function(resolve, reject) {
    click('#btn', resolve); // 绑定btn的点击事件
}).then(() => {
    return request(...);
}).then((vals) => {
    ...
})
复制代码

当第一次点击按钮,可以正常工作,但当第二次点击时,由于promise已经决议,后续的resolve将会被忽略。

虽然我们可以每次点击都新建一个promise,来解决这个问题,但是每次click都启动一个新的Promise序列,也不够理想。

无法取消

一旦创建了一个Promise,并为其注册了完成和拒绝处理函数,那么它就会开始执行,我们没有办法从外部停止它的进程。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享