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

相关推荐
anyup_前端梦工厂2 小时前
了解几个 HTML 标签属性,实现优化页面加载性能
前端·html
前端御书房2 小时前
前端PDF转图片技术调研实战指南:从踩坑到高可用方案的深度解析
前端·javascript
2301_789169542 小时前
angular中使用animation.css实现翻转展示卡片正反两面效果
前端·css·angular.js
Asthenia04123 小时前
浏览器缓存机制深度解析:电商场景下的性能优化实践
后端
风口上的猪20153 小时前
thingboard告警信息格式美化
java·服务器·前端
程序员黄同学3 小时前
请谈谈 Vue 中的响应式原理,如何实现?
前端·javascript·vue.js
databook4 小时前
『Python底层原理』--Python对象系统探秘
后端·python
爱编程的小庄4 小时前
web网络安全:SQL 注入攻击
前端·sql·web安全
宁波阿成5 小时前
vue3里组件的v-model:value与v-model的区别
前端·javascript·vue.js
柯腾啊5 小时前
VSCode 中使用 Snippets 设置常用代码块
开发语言·前端·javascript·ide·vscode·编辑器·代码片段