-
在Node.js中,使用Promise.prototype.finally
最近Promise.prototype.finally() 达到了TC39提案流程的第4阶段,这意味着其建议已被接受,并现已成为ECMAScript规范最新草案的一部分。由此看来,将其放入Node.js仅是时间问题。
本文将向您展示:如何使用Promise.prototype.finally()以及如何编写自己的简化polyfill。
一、什么是Promise.prototype.finally()
假设您创建了一个新的promise:
您可以使用.then()函数将诺言链接在一起。
请注意,它.then()带有两个功能参数。第一个是onFulfilled(),如果兑现了promise,就会调用。第二个是onRejected(),如果拒绝了promise,则调用。
promise是可以处于以下三种状态之一的状态机:
1.待定:基本操作正在进行中,但promise尚未实现或被拒绝
2.已完成:基础操作已成功完成,并且promise现在具有关联的价值
3.拒绝:基础操作由于某种原因而失败,并且promise现在具有关联的错误
此外,已兑现或已兑现的promise被称为“已结算”。
虽然.then()是承诺链的核心机制,但它并不是唯一的机制。promise也有一个.catch()功能是方便的错误处理。
该.catch()函数只是.then()使用onRejected处理程序而不使用onFulfilled处理程序的便捷速记:
就像.catch(),该.finally()功能是的便捷快捷方式.then()。区别在于,在兑现promise时即履行或拒绝promise时,.finally()执行功能onFinally。
.finally()在撰写本文时,该功能尚未包含在任何Node.js版本中,但promise.prototype.finally在npm上的模块具有polyfill。
上面的脚本将同时打印“已完成”和“已拒绝”,这是因为onFinally在实现promise时将调用处理程序,而不管promise是实现还是拒绝。然而,onFinally处理程序没有收到任何参数,所以你不能告诉的promise是否已兑现或拒绝。
该finally()函数返回一个承诺,让你可以更链.then(),.catch()和.finally()调用到返回值。finally()回报的promise将兑现与之挂钩的promise。例如,即使onFinally处理程序返回“ bar” ,下面的脚本仍将打印“ foo ”。
同样,即使该onFinally函数未触发任何错误,下面的脚本仍将打印“ foo” 。
上述脚本演示与工作的一个重要的细节finally():finally()不会为您处理promise rejections。finally()如何处理promise rejections值得更仔细的研究。
二、错误处理
该finally()功能并不意味着处理promise rejections。事实上,它会在函数执行后明确地抛出错误onFinally()。以下脚本将打印未处理的promise rejections警告。
像一样try/catch/finally,你通常想.finally()在一个链之后链接.catch()。
但是,该finally()函数返回一个Promise,因此没有什么可以阻止您在.catch()after之后链接.finally()。特别是,如果您的onFinally处理程序可能出错,例如,如果发出HTTP请求,则应.catch()在末尾添加a以处理可能发生的任何错误。
三、简化的Polyfill
我认为最简单的方法是编写自己的实现。该.finally()函数是一个不错的选择,因为官方的polyfill只有45行,并且大多数对于简单的概念证明不是必需的。
这是此简单的finally()polyfill可以解决的测试案例。下面的脚本应打印’foo’5次。
以下是简化的polyfill。
此实现背后的关键思想是onFinally处理程序可以返回promise。如果确实如此,则您需要.then()兑现该promise,并解决或拒绝最初的promise达成的目标。
您可以显式检查onFinally处理程序的返回值是否为Promise。但此时Promise.resolve()已经为您完成了此操作,并为您节省了几条if语句。
所以你只需确保跟踪初始promise所确定的值或错误,并确保返回的promise从finally()实现到初始已解决的值res,或重新抛出初始被拒绝的错误err。
四、继续
该Promise.prototype.finally()功能是撰写本文时8个第4阶段TC39提案之一,这意味着finally()Node.js还有7个其他新的核心语言功能。
该finally()功能是8个新功能中最令人兴奋的功能之一,因为它有望使异步操作后的清理工作更加整洁。例如,下面是我现在正在生产中运行的代码,在finally()函数执行完后,迫切需要释放锁。
对promise链感到困惑吗?异步/等待是在Node.js中撰写承诺的最佳方法。Await为您处理promise rejections,因此未处理的promise rejections就消失了。
我的新电子书Mastering Async / Await旨在使您对异步/等待的基础知识以及异步/等待如何在几小时内适应JavaScript生态系统有一个全面的了解。
原文:https://thecodebarbarian.com/using-promise-finally-in-node-js.html
翻译:新钛云服 魏建民