理解手动实现基础Promise

手动实现一个简单的 Promise 使得我们对 Promise 的深入理解,但是实现一个 Promise 会有哪些需求呢?

理解自定义 Promise 的需求

  • 一个构造函数,内部定义 Promise 的状态 pending/fulfilled/rejected 等相关数据。
  • 构造函数中参数执行器,执行器在实例化 Promise 的时候就开始执行。
  • then 方法,参数是两个函数,第一个是 成功 调用的方法,第二个是 失败 调用的方法。返回值是 新 的 Promise。
  • 状态转换。如果成功时,需要执行成功的回调,然后将状态 pending ->fulfilled。如果失败时,需要执行失败回调,然后将状态 pending->rejected 函数。
  • 异步实现。异步一般使用 setTimeout 和 setImmediate 或者其他的异步方案来实现即可。
  • 链式调用。then 种返回一个 Promise 即可。
  • 错误处理。链式调用的 catch 方法 或者 then 方法中的第二个函数。
  • 值(错误)传递。在状态转换的时候需要正确传递值和拒绝的原因。
  • 其他的方法。 Promise 还实现了很多其他的方法,更具需求自己实现。

构造函数

添加构造函数,并定义初始状态属性:

ts 复制代码
class MyPromise {
   constructor() {
        this.state = 'pending';
   }
}

添加 Promise 的执行

ts 复制代码
class MyPromise {
   constructor(executor) {
        this.state = 'pending';
   }
   
   try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
}

在内定义 executor 的参数决策成功和失败的函数

ts 复制代码
class MyPromise {
  constructor(executor) {
    this.state = 'pending';
    this.value = undefined;
    this.error = undefined;
    this.onFulfilled = [];
    this.onRejected = [];

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

    const reject = (error) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.error = error;
        this.onRejected.forEach((callback) => callback(this.error));
      }
    };

    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }
}
  • 决策成功的函数 resolve 调用将 state 转变成 fulfilled, resolve 决策的值时保存在 value 种,然后将 onFulfilled 中保存的函数,全部重新调用一次。onFulfilled 时值得关注 onFulfilled 数组中。
  • 决策失败的函数 reject 调用将 state 转换成 rejected。将 错误保存起来,然后遍历 onRejected 数组将所有函数执行一次。

在 Promise 示例化之后, 执行器 executor 需要立即执行。

then 方法

then 的逻辑是返回 新的 Promise

ts 复制代码
then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      if (this.state === 'fulfilled') {
        try {
          const result = onFulfilled(this.value);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      } else if (this.state === 'rejected') {
        try {
          const result = onRejected(this.error);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      } else {
        this.onFulfilled.push((value) => {
          try {
            const result = onFulfilled(value);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });

        this.onRejected.push((error) => {
          try {
            const result = onRejected(error);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });
      }
    });
}

测试用例

ts 复制代码
const p = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('success');
  }, 1000);
}
)

p.then((r) => {
  console.log(r)
}, (e) => {
  console.log(e)
})

const pe = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject('error');
  }, 1000);
}
)

pe.then((r) => {
  console.log(r)
}, (e) => {
  console.error("error", e)
})

完整实现

ts 复制代码
class MyPromise {
  constructor(executor) {
    this.state = 'pending';
    this.value = undefined;
    this.error = undefined;
    this.onFulfilled = [];
    this.onRejected = [];

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

    const reject = (error) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.error = error;
        this.onRejected.forEach((callback) => callback(this.error));
      }
    };

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

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      if (this.state === 'fulfilled') {
        try {
          const result = onFulfilled(this.value);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      } else if (this.state === 'rejected') {
        try {
          const result = onRejected(this.error);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      } else {
        this.onFulfilled.push((value) => {
          try {
            const result = onFulfilled(value);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });

        this.onRejected.push((error) => {
          try {
            const result = onRejected(error);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });
      }
    });
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }
}

小结

手动实现简单的 Promise, 关键在于理解 Promise 设计的业务模型,Promise 的实例化开始立即执行器中的函数 executor, 在内部定义 Promise 的状态,定义 Promise 所需要的执行器函数,已经在执行函数内部定义 resolve 和 reject 函数,最后还需要定义两个特殊的数组来处理进入 then 之后还是 pendding 状态处理函数,然后在角色之后遍历此数组接口。Promise 基本实现 then 方法以及 then 方法的链式调用,实现基本的 catch, catch 本质是一个特殊的 then 方法,只实现了 onRejected 部分。

相关推荐
星栈3 小时前
视频即代码,Remotion 能做什么、不能做什么
前端·音视频开发
广州华水科技3 小时前
单北斗GNSS位移监测系统的应用与技术解析
前端
用户47949283569153 小时前
从一句话或代码仓到可交互 HTML:开源 Agent 画图技能 Archify v3.2 实测与选型边界
前端·后端·面试
努力的小雨4 小时前
别再复制日志给AI了!我让Codex自己去观测云查报错
后端
风骏时光牛马5 小时前
生成一个AI多模态标题,仅输出一条标题,无额外文字、问句、备选、配图、文案等任何附加内容,不需要其他的任务服务 只要标题。
前端
wangruofeng6 小时前
从 GIF 到 AVIF:网页图片格式演进与 2026 年选型指南
前端·架构
afumu6 小时前
Go 写一个只监听 127.0.0.1 的控制服务:鉴权、白名单、危险命令拦截
后端·安全·go
清晨Coding7 小时前
为什么用 React Developer Tools 查看组件树这么乱?
前端·react.js
johnjincaaaa7 小时前
猿人学第 18 题「jsvmp 洞察先机」逆向通关实录
javascript·后端
用户4702784004057 小时前
C语言编译与链接
后端·开源