理解手动实现基础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 部分。

相关推荐
uzong1 小时前
技术故障复盘模版
后端
GetcharZp2 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
加班是不可能的,除非双倍日工资2 小时前
css预编译器实现星空背景图
前端·css·vue3
桦说编程2 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研2 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi3 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip3 小时前
vite和webpack打包结构控制
前端·javascript
excel3 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国4 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼4 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin