JavaScript
await 关键字可以被用来等待一个 Promise 被解决并返回其实现的值。如果传给 await 的值不是一个 Promise,那它会把这个值转化为一个已解决的 Promise。
向async函数迁移如果你的 Node.js 应用已经在使用Promise,只需要把原先的链式调用改写这些 Promise 进行 await。如果应用还在使用回调函数,应该以渐进的方式转向使用 async 函数。可以在开发一些新功能的时候使用这项新技术。必须调用一些旧有的代码时,可以简单地把它们包裹成为 Promise 再用新的方式调用。要做到这一点,可以使用内建的 util.promisify方法:
Async 函数的最佳实践在 express 中使用 async 函数express 本来就支持 Promise,所以在 express 中使用 async 函数是比较简单的:
但正如 Keith Smith 所指出的,上面这个例子有一个严重的问题——如果 Promise 最终被拒绝,由于这里没有进行错误处理,那这个 express 路由处理器就会被挂起。为了修正这个问题,把异步处理器包裹在一个对错误进行处理的函数中:
并行执行比如说正在编写这样一个程序,一个操作需要两个输入,其中一个来自于数据库,另一个则来自于一个外部服务:
代码会首先去获取 user,然后获取 product,最后再进行支付。由于前两步之间并没有相互依赖关系,其实完全可以将它们并行执行。应该使用 Promise.all 方法:
而有时候,只需要其中最快被解决的 Promise 的返回值——可以使用 Promise.race 方法。错误处理考虑下面这个例子:
当执行这段代码的时候,你会看到类似这样的信息:(node:69738) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: error(node:69738) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.在较新的 Node.js 版本中,如果 Promise 被拒绝且未得到处理,整个 Node.js 进程就会被中断。因此必要的时候你应该使用 try-catch:
可是,使用 try-catch 可能会隐藏掉一些重要的异常,比如像系统错误,你可能更想把它再抛出来。关于在什么情况下你应该将错误再次抛出,我强烈建议你去读一下 Eran 的这篇文章。更为复杂的流程控制Caolan McMahon 的 async 是一个出现较早的用于 Node.js 中异步流程控制的库。它提供了一些进行异步操作控制的帮助工具,比如:mapLimit,filterLimit,concatLimit,以及 priorityQueue。如果你不打算重新发明轮子,不想把同样的逻辑自己再实现一遍,并且愿意信赖这个经过实践检验的、每月下载量高达 5000 万的库,你可以结合 util.promisify 简单地重用这些函数: