π Disallow async functions as Promise#finally() callbacks.
πΌ This rule is enabled in the following configs: β
recommended, βοΈ unopinionated.
Passing an async function to Promise#finally() can hide the original promise outcome. If the promise rejects and the async finalizer also rejects, the resulting promise rejects with the finalizer error instead of the original error.
This rule reports async finalizer callbacks that are directly passed to .finally() or referenced through a local function declaration or const variable.
// β
promise.finally(async () => {
await cleanup();
});
// β
promise.finally(() => {
cleanupSynchronously();
});// β
async function cleanup() {}
promise.finally(cleanup);
// β
function cleanup() {}
promise.finally(cleanup);If cleanup must be asynchronous, handle its errors explicitly so they do not replace the original rejection:
// β
promise.finally(() => {
return cleanup().catch(error => {
logCleanupError(error);
});
});The behavior can be seen with this example:
const original = new Error('original');
const cleanup = new Error('cleanup');
try {
await Promise.reject(original).finally(async () => {
await Promise.reject(cleanup);
});
} catch (error) {
console.log(error.message);
//=> 'cleanup'
}This rule only reports callbacks it can locally identify as async. Imported functions, member expressions, and other dynamic callback references are ignored.