lately Promise.prototype.finally() Reached TC39 In the proposal process 4 Stage , This means that its proposal has been accepted , And it has become ECMAScript Part of the latest draft of the code . It seems , Put it in the Node.js It's just a matter of time .
This article will show you ： How to use Promise.prototype.finally() And how to write your own simplification polyfill.
One 、 What is? Promise.prototype.finally()
Suppose you create a new promise：
You can use .then() Function to link promises together .
Please note that , it .then() With two function parameters . The first is onFulfilled(), If it's cashed in promise, Will call . The second is onRejected(), If you refuse promise, Call .
promise Is a state machine that can be in one of the following three states ：
1. undetermined ： Basic operation in progress , but promise Not yet realized or rejected
2. Completed ： The basic operation has been successfully completed , also promise Now it has relevance value
3. Refuse ： The underlying operation failed for some reason , also promise Now there are related errors
Besides , Cashed or cashed promise go by the name of “ Settled ”.
although .then() It's the core mechanism of the commitment chain , But it's not the only mechanism .promise There is also a .catch() Function is convenient for error handling .
The .catch() Function is .then() Use onRejected Handle the program without using onFulfilled A handy shorthand for the handler ：
It's like .catch(), The .finally() Function is a convenient shortcut to .then(). The difference lies in , In cash promise To perform or reject promise when ,.finally() Executive function onFinally.
.finally() At the time of writing , This feature has not been included in any Node.js In the version , but promise.prototype.finally stay npm The module on has polyfill.
The script above will be printed at the same time “ Completed ” and “ Rejected ”, This is because onFinally In the realization of promise The handler is called when , Regardless of promise To realize or reject . However ,onFinally The handler did not receive any parameters , So you can't tell promise Whether it has been cashed or rejected .
The finally() Function returns a promise , So you can be more chained .then(),.catch() and .finally() Call to return value .finally() In return promise To which cash is linked promise. for example , Even if onFinally The handler returns “ bar” , The following script will still print “ foo ”.
Again , Even if it's time to onFinally Function did not trigger any errors , The following script will still print “ foo” .
The above script demonstrates and works with an important detail finally()：finally() I won't handle it for you promise rejections.finally() How to deal with it promise rejections It's worth studying more carefully .
Two 、 Error handling
The finally() Function doesn't mean processing promise rejections. in fact , It explicitly throws an error after the function is executed onFinally(). The following script will print the unprocessed promise rejections Warning .
Like the same try/catch/finally, You usually want to .finally() Link after a chain .catch().
however , The finally() The function returns a Promise, So nothing can stop you from .catch()after Then link to .finally(). especially , If your onFinally The handler may be wrong , for example , If send out HTTP request , You should .catch() Add... At the end a To handle any errors that may occur .
3、 ... and 、 A simplified Polyfill
I think the easiest way is to write your own implementation . The .finally() Function is a good choice , Because of the official polyfill Only 45 That's ok , And most of them are not necessary for simple proof of concept .
It's this simple finally()polyfill Test cases that can be solved . The following script should be printed 'foo'5 Time .
The following is a simplified polyfill.
The key idea behind this implementation is onFinally The handler can return promise. If so , Then you need to .then() Cash it promise, And resolve or reject the original promise Goals achieved .
You can explicitly check onFinally Whether the value is returned by the handler Promise. But this time Promise.resolve() This has been done for you , And save you a few if sentence .
So you just need to make sure you track the initial promise Determined value or error , And make sure the returned promise from finally() Implement to the initially resolved value res, Or re throw the initial rejected error err.
Four 、 continue
The Promise.prototype.finally() The function is when writing this article 8 First paragraph 4 Stage TC39 One of the proposals , It means finally()Node.js also 7 Other new core language features .
The finally() The function is 8 One of the most exciting of the new features , Because it is expected to make the cleaning after asynchronous operation Cleaner . for example , Here's the code I'm running in production right now , stay finally() After the function is executed , There is an urgent need to release the lock .
Yes promise Is the chain confused ？ asynchronous / Waiting is in Node.js The best way to write a commitment in .Await Handle for you promise rejections, So the untreated promise rejections It disappeared .
original text ：http://thecodebarbarian.com/using-promise-finally-in-node-js.html
translate ： New titanium cloud clothes Wei Jianmin