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

相关推荐
一袋米扛几楼9810 分钟前
【前端】从零开始的搭建顺序指南(技术栈:Node.js + Express + MongoDB + React)book-management
前端·node.js·express
~ 小团子15 分钟前
前后端分离: vue3+SpringBoot+ElementPlus+Axios+MyBatisPuls
java·spring boot·后端
ou.cs29 分钟前
ASP.NET Core 自动识别 appsettings.json的机制解析
后端·asp.net
yzhSWJ38 分钟前
CSS Position 属性完全指南
前端·css
xcLeigh44 分钟前
HTML5好看的水果蔬菜在线商城网站源码系列模板7
前端·html·html5
自珍JAVA1 小时前
Flowable
后端
非凡网站1 小时前
企业网站html源代码 企业网站管理源码模板
前端·html
brzhang1 小时前
接口又乱又难用?老司机带你掌握 8 个 API 设计绝招,告别低效协作!
前端·后端·架构
brzhang1 小时前
搞懂 HTTP/1、HTTP/2、HTTP/3:让你的 Web 应用快如闪电,面试不再怕!
前端·后端·架构
大鸡腿同学1 小时前
华丽的词藻,抵不过丰富的阅历
后端