I like to dig around the new features that are coming to JS, even when most of the time we need to transpile them down, you should know that you can, and should, deploy to production using ES2015+ syntax today. In the current list of proposals in stage-3, was something that catch my attention. That was the Promise.prototype.finally.
FINALLY!
So we now have a finally method into Promise. A finally method will be called always, and doesn't care if the Promise was fulfilled or rejected. It will no alter the value of the resolve promise, but could reject the promise with a new reason. Currently there are several implementations in other future libraries in NPM, as in the current proposal is written. However this, soon to be standard, will allow to use the method in evergreen browsers.
When to use it
The finally statement is really common in programming, specially when dealing with external connections that must be closed even in an unsuccessful operation, such as reading external files or database operations. Such connections need to be closed, and doesn't matter if the operation was successful or not, we just need to close the connection.
How to use it
The finally method is really straightforward, every promise will have one, and it will return a promise as well, so you could chain as usual.
Promise
.resolve(3)
.finally(
() => {
console.log('FINALLY!');
return 4;
}
)
.then(
value => console.log(value) // Output: 3
);
As you may notice, resolving a value in the finally, have not effects. However, you should know that, per specification, a Promise can be rejected from a finally method.
Promise
.resolve(3)
.finally(
() => {
console.log('FINALLY!');
throw 4;
}
)
.then(
value => console.log(value) // Does not print
).catch(
error => console.log(error) // Output: 4
);
How to use it, today
Well, you could use one of the different future libraries, such Bluebird, or the finally shim and use it with ES2017, that have a new syntax to deal with promises, async
/await
. I really love them, and they are very handy to work with promises, writing code that looks very clean. This couple makes every function, an asynchronous function, that are resolved as a regular Promise. So, you could just do finally after the declaration of the async function.
const promiseA = async () => {
return await 3;
}
promiseA.finally(() => console.log('The promise either was a success or a failure'));
The finally method will be called, as per the specification. But, what if we need to try
/catch
inside the async function (That you should). Then, we could use the finally
statement.
const aSuperUsefulPromise = async () => {
try {
return await PromiseThatCouldThrow();
} catch (error) {
console.log(error);
// We don't modify the promise here, just catch the error and handle it.
} finally {
return await 4;
}
}
console.log(await aSuperUsefulPromise()) // Outputs: 4
Well, when dealing with try
/catch
/finally
you CAN modify the value of a resolved promise. And this is really important to notice and understand, as you may expect a different result. So, you should never return inside a finally statement. It maybe weird to you, cause JS have a implicit return statement, but that return will be called after the finally statement, not before.
Conclusion
The finally
method in Promises will be something, but we could accomplish more or less the same behavior using current try
/catch
/finally
statements, we need to be careful though.
I learn a lot writing this article, and I hope that you could understand a little more about the new finally
method. Thanks you for reading, and as usual, if I made a mistake, please, guide me in the comments below, I will deeply appreciate it.
Top comments (2)
Or you could use Bluebird and have
finally
and a crapton of other cool features + a more performant promise implementation than the native one.I do mention the use of Bluebird, but I wasn't aware about the performance of that implementation. Thanks you. :)