首发于tooling bits
JS Tips #1:Promise.all 处理 Rejection 的技巧

JS Tips #1:Promise.all 处理 Rejection 的技巧

翻译自:Promise.all for Rejections and Resolves,E 文好的去看原文吧。

Promise 可以说是 JS 中非常重要的特性,它能帮我们解决回调地狱的问题,即使是最新的 async/await 语法也常常结合 Promise 来使用。

Promise.all 这个 API 允许我们在多个操作完成之后继续做某些事情,遗憾的是 Promise.all 只会在所有传给他的 Promise 都 resolve 了之后才会 resolve,如果其中的一个 reject 了,那么 Promise.all 后面的 then 就不会被执行,catch 会被执行,比如下面的例子:

Promise.all([
    Promise.resolve(1),
    Promise.reject(0)
])
.then(() => { console.log('resolved!'); })
.catch(() => { console.log('failed!') });
// >> failed!

如果你需要在所有的 Promise 都结束之后执行某些操作,而不论他们是否成功,Promise.all 的这种机制就会成为一种限制,有个比较 trick 的办法是给 then 和 catch 传入相同的回调,显然,这会让代码的可读性大打折扣。

那么,我们如何让 Promise.all 坦然面对失败呢?Jake Archibald 给出了解决方案:

Promise.all(promises.map(p => p.catch(() => undefined)));

如果 Promise 的 catch 回调返回了 undefined,那么 Promise 的失败就会被当做成功来处理。下面是代码实例:

Promise.all([
    // Resolves
    Promise.resolve(1), 
    // Rejects after 2 seconds
    new Promise((resolve, reject) => setTimeout(() => reject(1), 2000))
].map(p => p.catch(() => undefined))).then(() => console.log('done!'));

// >> done!

虽然这种方式也比较 trick,但能让我们在不借助第三方库的情况下不关心 Promise 是否成功而去执行后续操作。

既然很多人都有这种需求,那么 JS 规范是不是该完善下了?没错,过些时日坑能你就可以用 Promise.prototype.finally 这种结构了,类似于 try catch finally 这种结构。

以上,本文完。

发布于 2017-05-18 07:34