js笔记之Promise(三)
js笔记之Promise(三)
1 使用 promise 进行错误处理
promise链在错误中处理中非常强大,当一个 promise 被 reject 时,控制权将移交至最近的 rejection 处理程序。这在实际开发中非常方便。例如:
1 | fetch('https://no-such-server.blabla') // reject |
2 隐式的try…catch
在 executor 周围的“隐式 try..catch
”自动捕获了 error,并将其变为 rejected promise。
1 | new Promise((resolve, reject) => { |
2 再次抛出(Rethrowing)
在平常的try…catch中,在catch中遇到我们无法处理的错误我们可以再次的抛出异常,对于promise来 说也是可以的。
如果在promise的.catch中使用throw, 那么控制权就会移交到下一个error的处理程序,如果正常处理error并且正常完成,那么就会到最近的then处理程序。下面是一个例子:
1 | // 执行流:catch -> then |
3 未处理的 rejection
如果一个error没有被处理,会发生什么?此时程序就会像正常开发中抛出了一个错误一样,脚本停止,然后生成一个全局的异常。
如果出现了一个 error,并且在这没有 .catch,那么 unhandledrejection 处理程序就会被触发,并获取具有 error 相关信息的 event 对象,所以我们就能做一些后续处理了。
通常此类 error 是无法恢复的,所以我们最好的解决方案是将问题告知用户,并且可以将事件报告给服务器。
在 Node.js 等非浏览器环境中,有其他用于跟踪未处理的 error 的方法。
4 Promise.all
并行执行多个promise, 并等待所有的promise都准备就绪,例如并行下载几个url。
语法:let promise = Promise.all(iterable);
,他接受一个可迭代对象,通常是一个项为promise的数组。并返回一个新的promise,当所有的promise 都 resolve时,新的promise才会resolve。并且其结果数组就是将成为新的promise的结果。
注意:结果数组中元素的顺序和在源promise中的顺序相同,不管每个promise执行时间的长短。
一个常见的技巧是:讲一个任务数组映射到一个promise, 然后将其包裹到promise.all。例如:
1 | let urls = [ |
又或者另外一个例子:
1 |
|
如果任意一个 promise 被 reject,由
Promise.all
返回的 promise 就会立即 reject,并且带有的就是这个 error。且其他的promise也会被忽略,它们的结果也被忽略。
5 Promise.allSettled
此API等待所有的 promise 都被 settle,无论结果如何,结果数组都具有一下:
{status:"fulfilled", value:result}
对于成功的响应,{status:"rejected", reason:error}
对于 error。
一个例子:我们想要获取(fetch)多个用户的信息。即使其中一个请求失败,我们仍然对其他的感兴趣。
1 | let urls = [ |
对于以上的每个 promise,我们都得到了其状态(status)和 value/reason
。
6 Promise.race
与 Promise.all
类似,但只等待第一个 settled 的 promise 并获取其结果(或 error)。
1 | Promise.race([ |
在这里第一个 promise 最快,所以它变成了结果。第一个 settled 的 promise “赢得了比赛”之后,所有进一步的 result/error 都会被忽略。
7 Pomise.any
与 Promise.race 类似,区别在于 Promise.any 只等待第一个 fulfilled 的 promise,并将这个 fulfilled 的 promise 返回。如果给出的 promise 都 rejected,那么返回的 promise 会带有 AggregateError —— 一个特殊的 error 对象,在其 errors 属性中存储着所有 promise error。
例如:
1 | Promise.any([ |
这里的第一个 promise 是最快的,但 rejected 了,所以第二个 promise 则成为了结果。在第一个 fulfilled 的 promise “赢得比赛”后,所有进一步的结果都将被忽略。
8 Promise.resolve
在现代的代码中,很少需要使用 Promise.resolve 和 Promise.reject 方法,因为 async/await 语法使它们变得有些过时了。
Promise.resolve(value)
用结果 value
创建一个 resolved 的 promise。
语法:let promise = new Promise(resolve => resolve(value));
大概的使用场景:当一个函数被期望返回一个 promise 时,这个方法用于兼容性。(译注:这里的兼容性是指,我们直接从缓存中获取了当前操作的结果 value
,但是期望返回的是一个 promise,所以可以使用 Promise.resolve(value)
将 value
“封装”进 promise,以满足期望返回一个 promise 的这个需求。)
9 Promise.reject
Promise.reject(error)
用 error
创建一个 rejected 的 promise。
语法:let promise = new Promise((resolve, reject) => reject(error));
实际上,这个方法几乎从未被使用过。
总结:
catch
处理 promise 中的各种 error:在reject()
调用中的,或者在处理程序中抛出的 error。- 如果给定
.then
的第二个参数(即 error 处理程序),那么.then
也会以相同的方式捕获 error。 - 在任何情况下我们都应该有
unhandledrejection
事件处理程序(用于浏览器,以及其他环境的模拟),以跟踪未处理的 error 并告知用户(可能还有我们的服务器)有关信息,以使我们的应用程序永远不会“死掉”。
Promise
类有 6 种静态方法:Promise.all
可能是在实战中使用最多的。