Promise.prototype.finally()
1. 是什么?
finally() 方法返回一个 Promise。在 promise 结束时,无论结果是 fulfilled 或 rejected,都会执行指定的回调函数。这为"无论 Promise 是否成功都需执行的代码"提供了一种方式。
finally无论 promise 成功还是失败都会被调用,且回调不接受任何参数;同时它会把原始值/异常透传给下一个 then/catch。
fetch(myRequest).finally(function () {
isLoading = false;
});
finally回调不接受任何参数(与then/catch不同),因为无法预知是成功还是失败。
2. 简单实现
Promise.prototype.finally = function (callback) {
const P = this.constructor;
return this.then(
(value) => P.resolve(callback()).then(() => value),
(reason) => P.resolve(callback()).then(() => { throw reason; })
);
};
- 关键点:
callback()也被包成 Promise,等它执行完再传递原本的value/reason,这样 finally 不会"吞掉"错误。 - 通过
this.constructor拿到当前的 Promise 构造器,这样子类(如MyPromise)继承finally时也能正确返回子类的实例。
3. 另一种实现(直接用 Promise.resolve)
如果不在乎子类继承,也可以写得更直观:
Promise.prototype.finally = function (callback) {
return this.then(
/* onFulfilled */
(res) => Promise.resolve(callback()).then(() => res),
/* onRejected */
(err) => Promise.resolve(callback()).then(() => { throw err; })
);
};
补充:原实现里
console.log(this)/console.log(promise)是调试残留,promise变量并未声明,运行时会报错;这里已删掉,只保留最终版实现。
4. 使用场景
- 关闭加载状态:网络请求完成后无论成功失败都关闭 loading。
- 清理资源:关闭连接、释放锁、移除事件监听。
- 埋点:成功失败都要统计的指标上报。
function upload(file) {
showLoading();
return fetch('/upload', { method: 'POST', body: file })
.then((res) => res.json())
.catch((err) => ({ error: err.message }))
.finally(() => hideLoading());
}
来源整理自:我的有道云笔记



