当前位置: 首页 > article >正文

JS手撕代码系列【手写实现Promise】

在这里插入图片描述

在 JavaScript 中,Promise 是一种用于处理异步操作的对象,它可以让异步代码更易于理解和管理。在本文中,我们将手写实现一个 Promise。

Promise 的基本概念

在介绍 Promise 的实现方法之前,让我们先回顾一下 Promise 的基本概念。
Promise 有三种状态:

  • Pending(进行中):初始状态,表示 Promise 实例正在进行中。
  • Fulfilled(已完成):表示异步操作已经完成,并且 Promise 实例已经获得了一个值。
  • Rejected(已失败):表示异步操作已经失败,并且 Promise 实例已经获得了一个失败原因。

当 Promise 实例从 Pending 状态转变为 Fulfilled 或者 Rejected 状态时,我们称之为 Promise 已经 settled。

Promise 的实现

我们将使用 ES6 的类来实现一个 Promise。Promise 类需要具备以下功能:

  • 接受一个 executor 函数作为参数,该函数将在 Promise 实例创建时立即执行,并传递两个回调函数,即 resolve 和 reject 函数。
  • 在 executor 函数内部,我们需要处理异步操作,如果操作成功,则使用 resolve 函数返回结果;如果操作失败,则使用 reject 函数返回错误信息。
  • Promise 实例需要提供 then 方法,该方法接受两个回调函数,即 onFulfilled 和 onRejected,分别在 Promise 转变为 Fulfilled 或者 Rejected 状态时执行。
  • 如果在 executor 函数执行过程中发生错误,Promise 实例应该转变为 Rejected 状态,并且使用 reject 函数返回错误信息。
  • Promise 实例可以链式调用 then 方法,每个 then 方法可以返回一个新的 Promise 实例,实现 Promise 链。

下面是我们的 Promise 类的基本实现:

class Promise {
  constructor(executor) {
    this.status = 'pending';
    this.value = null;
    this.reason = null;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (value) => {
      if (this.status === 'pending') {
        this.status = 'fulfilled';
        this.value = value;
        this.onFulfilledCallbacks.forEach((callback) => {
          callback(this.value);
        });
      }
    };

    const reject = (reason) => {
      if (this.status === 'pending') {
        this.status = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach((callback) => {
          callback(this.reason);
        });
      }
    };

    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    const newPromise = new Promise((resolve, reject) => {
      if (this.status === 'fulfilled') {
        setTimeout(() => {
          try {
            const result = onFulfilled(this.value);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        }, 0);
      }

      if (this.status === 'rejected') {
        setTimeout(() => {
          try {
            const result = onRejected(this.reason);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        }, 0);
      }

      if(this.status === 'pending') {
        this.onFulfilledCallbacks.push((value) => {
          setTimeout(() => {
            try {
              const result = onFulfilled(value);
              resolve(result);
            } catch (error) {
              reject(error);
            }
          }, 0);
    		});
        this.onRejectedCallbacks.push((reason) => {
          setTimeout(() => {
            try {
              const result = onRejected(reason);
              resolve(result);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });
      }
    });
    return newPromise;
  }
}

我们先创建了一个 Promise 类,其中包含了 Promise 的基本属性和方法。在构造函数中,我们定义了 status、value、reason 三个变量用于保存 Promise 的状态和值,以及 onFulfilledCallbacks 和 onRejectedCallbacks 两个数组用于保存 then 方法中传入的回调函数。
然后,我们创建了 resolve 和 reject 两个函数,分别用于处理 Promise 的 Fulfilled 和 Rejected 状态。在 try-catch 语句中,我们调用了 executor 函数,并将 resolve 和 reject 函数传入,以便在异步操作完成后调用。
接下来,我们实现了 then 方法。当 Promise 的状态为 Fulfilled 时,我们使用 setTimeout 函数将 onFulfilled 回调函数放入微任务队列中,以确保在本轮事件循环结束后执行。同样的,当 Promise 的状态为 Rejected 时,我们使用 setTimeout 函数将 onRejected 回调函数放入微任务队列中。
当 Promise 的状态为 Pending 时,我们将 onFulfilled 和 onRejected 回调函数保存到 onFulfilledCallbacks 和 onRejectedCallbacks 数组中,并在异步操作完成后执行。
最后,我们返回一个新的 Promise 实例,该实例包含了一个 executor 函数。在 executor 函数中,我们根据当前 Promise 的状态决定调用 onFulfilled 或 onRejected 回调函数,并将执行结果传递给 resolve 或 reject 函数。

使用手写Promise

现在,我们可以使用手写的 Promise 类来处理异步操作了。下面是一个简单的例子:

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Hello, world!');
  }, 1000);
});

promise
  .then((result) => {
    console.log(result);
    return 'Goodbye, world!';
  })
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.error(error);
  });

在这个例子中,我们创建了一个 Promise 实例,并在 1 秒钟后将状态设置为 Fulfilled,并返回一个字符串。
然后,我们链式调用了两个 then 方法,第一个方法打印了字符串并返回了一个新的字符串,第二个方法又打印了新的字符串。
最后,我们调用了 catch 方法,以处理任何可能发生的错误。

结论

Promise 是一种非常强大的异步编程技术,可以使我们更加轻松地管理异步代码。通过手写实现 Promise,我们可以更好地理解 Promise 的工作原理,并更加深入地了解 JavaScript 的异步编程模型。


http://www.kler.cn/a/15747.html

相关文章:

  • SQL Server 查询设置 - LIKE/DISTINCT/HAVING/排序
  • Python_爬虫3_Requests库网络爬虫实战(5个实例)
  • 在Ubuntu22.04上源码构建ROS noetic环境
  • Python知识点精汇!字符串:定义、截取(索引)和其内置函数
  • go 集成swagger 在线接口文档
  • 第9章 DIV+CSS布局作业
  • 【Redis16】Redis进阶:内存优化
  • wifi芯片行业信息汇总
  • AcWing55. 连续子数组的最大和
  • 【柒志科技】面经 base上海
  • 了解hiberfil.sys文件:计算机休眠模式的背后
  • 【数据治理】数据治理的定义和价值
  • 标准错误重定向
  • 2023-04-30:用go语言重写ffmpeg的resampling_audio.c示例,它实现了音频重采样的功能。
  • 在全志V851S开发板上使用SSH配置步骤分析
  • 前端小白是如何利用chatgt用一周时间从做一款微信小程序的
  • 【MATLAB数据处理实用案例详解(15)】——利用BP神经网络实现个人信贷信用评估
  • 零基础想成为黑客,只需要四步
  • CF662C Binary Table
  • nvm安装使用详解,附gnvm介绍
  • 史上最全的接口测试,吐血整理从零到接口自动化实战...
  • 1992-2022年31省人均gdp/各省人均地区生产总值
  • @PostConstruct注解和@PreDestroy注解
  • 【AI生产力工具】Upscale.media:用AI技术提升照片质量,让你的作品更出色
  • 【LeetCode股票买卖系列:121. 买卖股票的最佳时机 | 一次遍历 | 暴力递归=>记忆化搜索=>动态规划】
  • 系统集成项目管理工程师 笔记(第19章:项目收尾管理)