手写Promise-什么是Promise

在学习JS的异步编程时,你总是绕不Promise。在开发时总是会接触它,用时觉得也没有什么,用的时候感觉也就那样,但是到了面试时的时候,一道道要你说出执行顺序的时候又犯了难。不知道你是不是跟我一样有这样的感受。本系列将以手写Promise的方式来了解Promise,在手写Promise的同时体验到各种开发技巧。提高一下自身的开发思维。

那我们开始手写Promise的旅程吧!

什么是Promise

Promise是什么呢?可以想象现实生活中的一个小场景:淘宝购物

  1. 当你看到了心仪的商品时,你点击购买然后付钱后,此处于发货和配送中。
  2. 当心仪商品配送到家后,最终会产生两种结果:
    • 成功:实物和淘宝看到的一样非常满意。交易成功!
    • 失败:实物和淘宝看到的相差甚远不是很满意。退货!

我们再来看看Promise是怎样的呢?

  • Promise是一个对象,代表了一个异步操作最终完成的以及返回的结果。
  • Promise操作时有三种状态:
    • pending:初始状态,表示正在处理中。
    • fulfilled:操作成功完成
    • rejected:操作失败
  • Promise的状态一旦发生改变,不能更改。这是Promise的关键特性。

为什么需要Promise

在没有Promise的时候,是怎样编写异步代码的呢?主要是回调函数。可以想象下网络请求调用后台接口时,一个接口依赖一个接口再依赖另一个接口的场景。通过回调函数如何编写呢?

js 复制代码
/* jquery回调函数的书写方式 */
$.ajax({
  url: "/api/userInfo",
  type: "GET",
  dataType: "json",
  success: function (info) {
    $.ajax({
      url: "/api/roleInfo",
      data: { userId: info.id },
      success: function (role) {
        $.ajax({
          url: "api/menuInfo",
          data: { roleId: role.id },
          success: function () {
            /* 还有可能需要调用其他接口*/
          },
        });
      },
    });
  },
});

上述代码发现回调函数层层嵌套。形成了'金字塔'的形状。代码之间耦合度非常高,维护代码极其困难,一旦有错误处理起来比较困难。就像开发人员天天骂是一坨屎的代码。😂

Promise的出现便是为了解决这样的问题而诞生的。它通过.then.catch方法实现了链式调用。将异步的流程阅读性强,接近于同步线性流程。将上述代码改为promise的方式。

js 复制代码
/* jquery支持Promise的书写方式 */
$.ajax({
  url: "/api/userInfo",
  type: "GET",
  dataType: "json",
})
  .then((info) => $.ajax({ url: "/api/roleInfo", data: { userId: info.id } }))
  .then((role) => $.ajax({ url: "/api/menuInfo", data: { roleId: role.id } }))
  .then(function (menu) { /* 还可以继续处理 */ })
  .fail((error) => {  /* 处理错误 */ });

修改后的代码从上往下的线性结构,在阅读代码和可维护性上都大大提升。错误处理上更加方便。

基本用法

知道promise为什么出现后,也知道了它的好处,那我们要如何使用它呢?首先要知道Promise是一个构造函数(new Promise(executor))。接收一个参数executor函数。此函数会立刻执行,它接收两个参数(也是函数):

  • resolve: 当异步操作成功时调用,将状态pending改为fulfilled
  • reject: 当异步操作失败时调用,将状态pending改为rejected
js 复制代码
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = true;
    if(success) {
        resolve('操作成功');
        // reject('失败了'); // 此处不会执行 状态改为了fulfilled 不能再改为
    } else {
        reject('拒绝此操作');
        // resolve('成功啦'); // 此处不会执行 状态改为了rejected 不能再改为
    }
  }, 1000)
})

Promise通过.then().catch().finally()来接收成功和失败结果。

  • .then(onFulfilled, onRejected):接收两个回调函数,分别处理成功和失败。然后返回一个新的Promise,这便是可以链式调用的原因。
  • .catch(onRejected) :专门处理失败的,其实就是.then(null, onRejected)的语法糖。
  • .finally(onFinally):无论成功或失败都会执行,一般用于清理工作。
js 复制代码
const p = new Promise((resolve, reject) => {
  resolve("lucy");
})
  .then((name) => {
    console.log(`接收到了面试人:${name}`); // 此处会执行
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("finally"); // 不管成功失败,都会执行
  });

小结

本文讲述内容如下:

  • 什么是Promise,它是一个构造函数,接收一个函数,初始化立即执行,此函数分别接收处理成功和失败的函数。
  • Promise本质是一个状态机,包括三种状态: pendingfulfilledrejected。状态一旦改变则不可逆
  • then方法主要注册回调函数到对应状态上,并返回一个新的Promise以支持链式调用
  • catch方法专门处理失败,finally方法是不管成功失败都会执行。
  • Promise底层里的then/catch不是立即执行的,它是放入了微任务队列中,等待渲染主线程检测到后执行的。

了解Promise之后,接下来进行手写Promise工作了。

相关推荐
mCell2 小时前
AI 时代 SVG 画图的潜力
前端·agent·svg
我命由我123458 小时前
CesiumJS 笔记 - 获取容器中心点、Cartesian3 clone 方法、修改 Cartesian3 对象的高度
前端·javascript·css·前端框架·html·html5·js
Hopebearer_9 小时前
页面突然只剩 DOM?一次静态资源版本错配排查
前端·部署
抱抱宝9 小时前
Agent-study项目教程(03):手写 Mini-ReAct Agent(不依赖框架)
javascript·人工智能·gpt·react.js·prompt·agent
东风破_9 小时前
ESLint 是什么?为什么你的项目需要它?
前端·后端·代码规范
用户938515635079 小时前
Next.js 笔记系统(二):Redis 数据服务与侧边栏组件拆分实战
javascript·全栈
圣殿骑士-Khtangc11 小时前
Go字符串高效拼接性能对比与底层原理分析
服务器·前端·golang
BigTopOne11 小时前
【ijkplayer】 硬解码流程
前端
kyriewen12 小时前
DeepSeek Harness开源第一天我就上手了——和Claude Code的差距比想象中大
前端·ai编程·deepseek
捡田螺的小男孩12 小时前
什么是 Skill?手把手带你写一个简单有用的 Skill!
前端·后端·程序员