实现 promise.finally

Promise.prototype.finally() 方法返回一个Promise。它在Promise被解决(无论是fulfilled还是rejected)后都会执行指定的回调函数。这为在Promise是否成功完成后都需要执行的代码提供了一种方便的方式。finally并不会改变Promise的结果值,而是返回原Promise或者一个新的Promise。

实现Promise.prototype.finally

要实现finally方法,我们需要考虑以下几点:1. finally回调不接受任何参数,因为它的目的是在Promise完成后执行一些清理工作,而不关心Promise的结果。2. finally应该返回一个Promise,这个Promise的解决状态和原Promise相同。3. 如果finally回调中返回了一个Promise,那么外部链上的后续Promise应该等待这个Promise也完成后才继续执行。基于以上考虑,我们可以这样实现Promise.prototype.finally:

js 复制代码
Promise.prototype.finally = function(callback) {
  // `this` 指向当前Promise实例
  return this.then(
    // Promise成功时执行的函数
    value => Promise.resolve(callback()).then(() => value),
    // Promise失败时执行的函数
    reason => Promise.resolve(callback()).then(() => { throw reason; })
  );
};

解释

  • this.then(...):我们通过调用.then方法来确保无论原Promise是fulfilled还是rejected,callback都会被执行。

  • value => Promise.resolve(callback()).then(() => value):如果原Promise成功,我们首先执行callback,并确保callback的返回值(如果有的话)被Promise.resolve包装,这样即使callback返回了一个Promise,它也会被正确处理。之后,我们通过.then(() => value)确保返回一个新的Promise,这个Promise解决为原Promise的值。

  • reason => Promise.resolve(callback()).then(() => { throw reason; }):如果原Promise失败,处理方式类似,不同之处在于我们需要通过throw reason来确保返回的Promise被拒绝,并且拒绝的原因与原Promise相同。

js 复制代码
let promise = new Promise((resolve, reject) => {
  setTimeout(() => resolve("result"), 1000);
});

promise
  .then(result => console.log(result))
  .finally(() => console.log("Promise completed"))
  .then(() => console.log("Chain continued"));

在这个示例中,无论promise是成功还是失败,"Promise completed"都会被打印出来。而且,由于finally不改变Promise的结果,所以"Chain continued"也会在finally之后被打印。通过这种方式,finally提供了一种无论Promise结果如何都需要执行某些操作的简洁方法,这在进行资源清理等操作时特别有用。

相关推荐
陈随易12 分钟前
前端项目部署只要30秒
前端·后端·程序员
本末倒置18314 分钟前
从 Vue CLI 迁移到 Rsbuild 后,JSX 突然全挂了?一次排查记录
前端
古夕14 分钟前
多应用同域部署下 Favicon 异常问题排查与治理
前端·javascript
YIAN16 分钟前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp
Imchendiana16 分钟前
《狂人日记NO.9》— 前后端一把梭,我的全栈实录
前端·后端
逍遥运德23 分钟前
前端工程化-03:包管理NPM-package.json 和 package-lock.json 详解
前端·前端框架·前端工程化
逗逗豆巴吧28 分钟前
WPS 加载项中实现当前文档直接上传
前端·javascript·ecmascript 6
慢功夫28 分钟前
💡【调试】按下 F5 后,mini-vscode 到底做了什么
前端·visual studio code
妙码生花30 分钟前
从 PHP 到 AI + Golang,程序员自救转型手记(二十一):网络请求封装优化
前端·javascript·vue.js
用户114818678948432 分钟前
普通Fetch、Fetch流式、Axios、SSE:谁才是流式输出的正确操作?
前端·javascript