理解promise原理,手写promise思路

60 阅读3分钟

先给大家回忆下promise的基础使用

// 创建一个 Promise 对象
  const myPromise = new MyPromise((resolve, reject) => {
      // 模拟异步操作
      setTimeout(() => {
          //  const randomNumber = Math.random();
          const randomNumber = 0.2;
          console.log(randomNumber);
          if (randomNumber > 0.5) {
              // 异步操作成功,调用 resolve 并传递结果
              resolve(randomNumber);
          } else {
              // 异步操作失败,调用 reject 并传递错误信息
              reject(new Error("异步操作失败"));
          }
      }, 2000);
  });

  // 使用 Promise 对象
  myPromise
      .then((result) => {
          // 异步操作成功后的处理
          console.log("成功:", result);
      }, (error) => {
          // 异步操作失败后的处理
          console.log("失败:", error);
      });

接下来开始手写promise 第一步就是要先定义状态

const PENDING = "pending";
const RESOLVE = "resolve";
const REJECT = "reject";

第二步就是执行传入的promise参数的函数fn

function MyPromise(fn) {

     //将两个回调函数传入,并执行函数
     try {
         fn(resolve, reject);
     } catch (error) {
         reject(error);
     }
 }

第三步初始化内部变量

 //保存初始状态,value用于保存resolve或reject函数传入的参数
     let self = this;
     this.value = null;
     this.status = PENDING;

     //存储then中的resolve,reject的回调函数
     this.resolvedCallbacks = [];
     this.rejectedCallbacks = [];

第四步,定义resolve,和reject函数

function resolve(value) {
         //如果参数是promise,则状态改变必须等待前一个状态改变后
         if (value instanceof MyPromise) {
             return value.then(resolve, reject);
         }

         //使得在then函数中完成resolve或reject注册后再进行调用这里
         setTimeout(() => {
             if (self.status === PENDING) {
                 self.status = RESOLVE;
                 self.value = value;
                 self.resolvedCallbacks.forEach(callback => {
                     callback(value);
                 })
             }
         }, 0)
     }

     function reject(value) {
         setTimeout(() => {
             if (self.status === PENDING) {
                 self.status = REJECT;
                 self.value = value;
                 self.rejectedCallbacks.forEach(callback => {
                     callback(value);
                 })
             }
         }, 0)
     }

第五步,为promise添加then方法

 MyPromise.prototype.then = function(onResolved, onRejected) {
     //因为是可选参数,所以先判断参数类型
     onResolved = typeof onResolved === 'function' ? onResolved : function(value) { return value };
     onRejected = typeof onRejected === 'function' ? onRejected : function(value) { return value };
     //如果是等待状态,就加入函数队列,既注册函数
     if (this.status === PENDING) {
         this.resolvedCallbacks.push(onResolved);
         this.rejectedCallbacks.push(onRejected);
     }

     //如果不是等待状态就直接执行函数
     if (this.status === RESOLVE) {
         onResolved(this.value);
     }

     if (this.status === REJECT) {
         onRejected(this.value);
     }
 }

这样一个基础的promise就完成了,让我觉得比较有意思的是resolve和reject函数中的setTimeout的使用,这里为什么要使用setTimeout呢,因为我们一般是这样用promise的

  const myPromise = new MyPromise((resolve, reject) => {
              resolve(111);
  });
  myPromise
      .then((result) => {
          console.log("成功:", result);
      });

如果不给resolve加setTimeout的话,在同步线程里,resolve函数就会先执行,那resolve里运行 self.resolvedCallbacks.forEach(callback => { callback(value); })时就会找不到回调函数,因此必须把这个操作放入异步队列里,保证它是本轮循环最后执行的代码。

完整代码

//定义状态
 const PENDING = "pending";
 const RESOLVE = "resolve";
 const REJECT = "reject";

 function MyPromise(fn) {

     //保存初始状态,value用于保存resolve或reject函数传入的参数
     let self = this;
     this.value = null;
     this.status = PENDING;

     //存储then中的resolve,reject的回调函数
     this.resolvedCallbacks = [];
     this.rejectedCallbacks = [];

     function resolve(value) {
         //如果参数是promise,则状态改变必须等待前一个状态改变后
         if (value instanceof MyPromise) {
             return value.then(resolve, reject);
         }

         //使得在then函数中完成resolve或reject注册后再进行调用这里
         setTimeout(() => {
             if (self.status === PENDING) {
                 self.status = RESOLVE;
                 self.value = value;
                 self.resolvedCallbacks.forEach(callback => {
                     callback(value);
                 })
             }
         }, 0)
     }

     function reject(value) {
         setTimeout(() => {
             if (self.status === PENDING) {
                 self.status = REJECT;
                 self.value = value;
                 self.rejectedCallbacks.forEach(callback => {
                     callback(value);
                 })
             }
         }, 0)
     }

     //将两个回调函数传入,并执行函数
     try {
         fn(resolve, reject);
     } catch (error) {
         reject(error);
     }
 }

 MyPromise.prototype.then = function(onResolved, onRejected) {
     //因为是可选参数,所以先判断参数类型
     onResolved = typeof onResolved === 'function' ? onResolved : function(value) { return value };
     onRejected = typeof onRejected === 'function' ? onRejected : function(value) { return value };
     //如果是等待状态,就加入函数队列,既注册函数
     if (this.status === PENDING) {
         this.resolvedCallbacks.push(onResolved);
         this.rejectedCallbacks.push(onRejected);
     }

     //如果不是等待状态就直接执行函数
     if (this.status === RESOLVE) {
         onResolved(this.value);
     }

     if (this.status === REJECT) {
         onRejected(this.value);
     }
 }