新手也能看懂的Promise原理,超简单!不来看一下吗?

653 阅读16分钟

1 简易版

我们先来使用下原生的Promise,然后在使用的过程中注意几个点,再根据这些点来自己实现一遍Promise。

 const p0 = new Promise((resolve, reject) => {
   resolve(1);
 });
 ​
 p0.then(
   (res) => {
     console.log(res);
   },
   (err) => {
     console.log(err);
   }
 );

上述代码很简单,p0是个新的Promise实例,Promise构造函数接受一个执行器函数,执行器函数会接受两个参数,一个是resolve函数,用来将Promise实例p0的状态由pending改成resolved。 接着,调用p0then函数,then函数接受两个函数,第一个函数会在p0的状态变成resolved的时候触发执行,第二个函数会在p0的状态变成rejected的时候执行。 由此,我们总结一下Promise构造函数的几个点:

  1. Promise构造函数接受一个执行器函数,该执行器函数会接受两个函数参数,分别用来改变Promise实例的状态。

  2. 同时,Promise实例的状态只能被改变一次,也就是只能从pengding->resolved,或者从pendingrejected,不能是resolved->resolved,或者rejected->rejected,因此我们在改变状态的时候需要先判断一下。

    根据这以上这两点,我们可以写出如下代码:

     function _Promise(executor) {
       this.status = 'pending';
       
       function resolve () {
          if (this.status === 'pending') {
            this.status = 'resolved';
          }
        } 
       
       function reject () {
         if (this.status === 'pending') {
           this.status = 'rejected';
         }
       }
       excutor(resolve, reject);
     }
    

    不知道大家发现没有,这个代码是有this指向问题的,_Promise是个构造函数,因此最外面用this没问题,这个this会指向new _Promise(xx)生成的对象,也就是p0。但是在resolve函数和reject函数内部,其this是指向全局变量的。因为函数中this的指向,要么指向调用函数的对象,要么指向被apply之类绑定的对象,最后就是指向全局变量了,我们这里符合的是最后一种情况,这一点如果大家不理解,可以先暂停去了解一下。因此,我们需要修改下代码,在外面保存this,然后再传进resolvereject函数内部。

     function _Promise(executor) {
       const _self = this;
       _self.status = 'pending';
       
       function resolve () {
          if (_self.status === 'pending') {
            _self.status = 'resolved';
          }
        } 
       
       function reject () {
         if (_self.status === 'pending') {
           _self.status = 'rejected';
         }
       }
     ​
       executor(resolve, reject);
     }
    
  3. resolvereject是需要接受参数的,因此我们还需要改进下,把resolvereject函数的的入参保存起来。另外,在执行executor的时候,有可能会报错,因此我们需要用try-catch包裹executor的执行,在报错的时候执行reject函数,毕竟报错也会导致Promise状态的改变。改进后的代码如下:

     function _Promise(executor) {
       const _self = this;
       _self.status = 'pending';
       _self.value = undefined; // 保存resolve函数的入参
       _self.reason = undefined; // 保存reject函数的入参
       
       function resolve(res) {
         if (_self.status === 'pending') {
           _self.status = 'resolved';
           _self.value = res;
         }
       }
     ​
       function reject(err) {
         if (_self.status === 'pending') {
           _self.status = 'rejected';
           _self.reason = err;
         }
       }
       
       try {
         executor(resolve, reject);
       } catch (e) {
         reject(e);
       }
     }
    
  4. 到这里,我们的执行器就差不多了,当然这只是简易版的,后续还会继续优化。接下来我们实现then方法:Promise实例是有then方法的,因此,我们需要在自定义的_Promise的原型链上实现then方法,这样实例化后的p0才能调用then方法。

     _Promise.prototype.then = function () {}
    
  5. 接着,then方法接受两个参数,这两个参数都是函数,第一个参数会在p0的状态变成resolved的时候触发,第二个参数会在p0的状态变成rejected的时候触发。我们调用then的方式,是p0.then(xxx),因此,在then内部,是可以通过this获取到p0的。根据这一点,我们来实现下then方法:

     _Promise.prototype.then = function (onResolved, onRejected) {
       const _self = this;
       switch (_self.status) {
         case 'resolved':
           onResolved(_self.value);
           break;
         case 'rejected':
           onRejected(_self.reason);
           break;
         default:
           break;
       }
     };
    

    上述代码中,我们同样在第二行用_self获取了p0对象,然后判断当前p0对象的状态,如果是resolved的话,就执行then函数的第一个函数参数onResolved,并传入_self.value,如果是rejected的话,就执行第二个函数参数onRejected,并传入_self.reason

以上就是简易版Promise的实现了,我们实现了构造器函数,实现了原型链上的then函数,是不是非常简单?现在让我们测试一下:

 const p0 = new _Promise((resolve, reject) => {
   resolve(1);
 });
 ​
 p0.then(
   (res) => {
     console.log(res);
   },
   (err) => {
     console.log(err);
   }
 );

这个测试代码跟我们最开始使用原生Promise只有一点不同,那就是构造函数换成了我们自定义的_Promise,而最后的执行结果,跟使用原生Promise的一模一样!!

这就是简易版的Promise,之所以说是简易版,是因为它是有缺陷的,它不支持异步调用,也就是说,如果在构造函数_Promise中异步执行resolve(),那它是不能正常工作的,测试代码如下:

 const p0 = new _Promise((resolve, reject) => {
   setTimeout(() => {
     resolve(1);
   });
 });
 ​
 p0.then((res) => {
   console.log(res);
 });
 // 没有输出1

它还有其他问题,比如说还不支持链式调用,不过我们一步一步来,目前先解决下这个异步调用的先。

2 修复构造函数中异步处理

我们先分析下为什么异步调用不能如期工作:

  1. 首先,我们在new _Promise(executor)的时候,执行器executor是会被同步执行的,只是resolve(1)由于被setTimeout包裹,因此变成了异步。
  2. 其次,同步执行完executor之后,会马上同步执行then方法,而我们在then方法里面,会根据当前实例的状态,如果是resolved,就执行then的第一个参数,也就是onResolved方法,如果是rejected,就执行then的第二个参数,也就是onRejected方法。
  3. 但是现在,由于resolve(1)被异步了,因此在同步执行then方法的时候,resolve(1)还没被执行,此时当前实例的状态还是pending,而我们在switch case中没有判断pending状态该怎么处理,因此就会在pending状态这里结束了,也就没有输出1了。

明白了原因,那我们就来修复一下then,在switch case的时候补充一个pending状态就好了。

 _Promise.prototype.then = function (onResolved, onRejected) {
   const _self = this;
   switch (_self.status) {
     case 'resolved':
       onResolved(_self.value);
       break;
     case 'rejected':
       onRejected(_self.reason);
     case 'pending':
       _self.onResolvedCallbacks.push(() => onResolved(_self.value));
       _self.onRejectedCallbacks.push(() => onRejected(_self.reason));
       break;
     default:
       break;
   }
 };

pending状态的情况下,我们用箭头函数封装一下onResolved(_self.value),然后pushonResolvedCallbacks,对于onRejected也做同样的处理。 这里我们引入了新的变量onResolvedCallbacks用来存放pending状态下onResolved函数,这个变量是数组,为什么是数组呢?因为p0是可以多次调用then方法的,比如:

 const p0 = new Promise((resolve, reject) => {
   setTimeout(() => {
     resolve(1);
   });
 });
 ​
 p0.then((res) => {
   console.log(res);
 });
 ​
 p0.then((res) => {
   console.log(res);
 });

在使用原生Promise的时候,这种情况下会输出两次1。因此,我们的存放pending状态下onResolved函数的变量onResolvedCallbacks也要是一个数组,这样才能满足这种异步resolve下多次调用then的情况,否则,如果是常规的变量,多次调用then时,后者就会覆盖前者。

 case 'pending':
   _self.onResolvedCallbacks = () => onResolved(_self.value);
   _self.onRejectedCallbacks = () => onRejected(_self.reason);
   break;

这种情况下,要是异步resolve下多次调用then,由于此时都是pengding状态,那么后者onResolvedCallbacks就会覆盖前者,所以要用数组。

既然使用了新的变量,那么我们就要改一下构造函数_Promise了。

 function _Promise(executor) {
   const _self = this;
   _self.status = 'pending';
   _self.value = undefined; // 保存resolve函数的入参
   _self.reason = undefined; // 保存reject函数的入参
   _self.onResolvedCallbacks = []; // 保存pending状态下的onResolved函数
   _self.onRejectedCallbacks = []; // 保存pending状态下的onRejected函数
 ​
   function resolve(res) {
     if (_self.status === 'pending') {
       _self.status = 'resolved';
       _self.value = res;
       // 一旦 resolve 执行,遍历执行已收集到的 onResolved 回调函数,并重置 onResolvedCallbacks
       _self.onResolvedCallbacks.forEach((fn) => fn());
       _self.onResolvedCallbacks = [];
     }
   }
 ​
   function reject(err) {
     if (_self.status === 'pending') {
       _self.status = 'rejected';
       _self.reason = err;
       // 一旦 reject 执行,遍历执行已收集到的 onRejectedCallbacks 回调函数,并重置 onRejectedCallbacks
       _self.onRejectedCallbacks.forEach((fn) => fn());
       _self.onRejectedCallbacks = [];
     }
   }
 ​
   try {
     executor(resolve, reject);
   } catch (e) {
     reject(e);
   }
 }

我们在构造函数里加了两个变量:用来保存pending状态下的onResolved函数的onResolvedCallbacks变量,以及保存pending状态下的onRejected函数的onRejectedCallbacks变量。 接着,在resolve或者reject的时候,遍历onResolvedCallbacks或者onRejectedCallbacks变量,执行里面保存的函数。 这样,我们就能实现异步resolve()时也能正常调用then了!

完整的代码如下:

 function _Promise(executor) {
   const _self = this;
   _self.status = 'pending';
   _self.value = undefined; // 保存resolve函数的入参
   _self.reason = undefined; // 保存reject函数的入参
   _self.onResolvedCallbacks = []; // 保存pending状态下的onResolved函数
   _self.onRejectedCallbacks = []; // 保存pending状态下的onRejected函数
 ​
   function resolve(res) {
     if (_self.status === 'pending') {
       _self.status = 'resolved';
       _self.value = res;
       // 一旦 resolve 执行,遍历执行已收集到的 onResolved 回调函数,并重置 onResolvedCallbacks
       _self.onResolvedCallbacks.forEach((fn) => fn());
       _self.onResolvedCallbacks = [];
     }
   }
 ​
   function reject(err) {
     if (_self.status === 'pending') {
       _self.status = 'rejected';
       _self.reason = err;
       // 一旦 reject 执行,遍历执行已收集到的 onRejectedCallbacks 回调函数,并重置 onRejectedCallbacks
       _self.onRejectedCallbacks.forEach((fn) => fn());
       _self.onRejectedCallbacks = [];
     }
   }
 ​
   try {
     executor(resolve, reject);
   } catch (e) {
     reject(e);
   }
 }
 ​
 _Promise.prototype.then = function (onResolved, onRejected) {
   const _self = this;
   switch (_self.status) {
     case 'resolved':
       onResolved(_self.value);
       break;
     case 'rejected':
       onRejected(_self.reason);
     case 'pending':
       _self.onResolvedCallbacks.push(() => onResolved(_self.value));
       _self.onRejectedCallbacks.push(() => onRejected(_self.reason));
       break;
     default:
       break;
   }
 };
 ​
 const p0 = new _Promise((resolve, reject) => {
   setTimeout(() => {
     resolve(1);
   });
 });
 ​
 p0.then((res) => {
   console.log(res);
 });
 ​
 p0.then((res) => {
   console.log(res);
 });

执行后,我们的终端也能正常输出两次1啦!!恭喜你,我们实现了异步的Promise:核心就是pending状态时收集then的回调函数onResolvedonRejected,然后在resolve或者reject的时候遍历执行收集到的onResolved或者onRejected

不过到这里,还没结束,我们的_Promise.then不支持链式调用,要支持链式调用的话,需要在then里返回一个新的_Promise对象。那就,返回呗!

3 修复链式调用

刚才我们分析了下,若要链式调用then方法的话,需要then返回一个_Promise对象,而我们前面这版并没有做到这点,因此无法链式调用then方法。

 _Promise.prototype.then = function (onResolved, onRejected) {
   const _self = this;
   switch (_self.status) {
     case 'resolved':
       onResolved(_self.value);
       break;
     case 'rejected':
       onRejected(_self.reason);
     case 'pending':
       _self.onResolvedCallbacks.push(() => onResolved(_self.value));
       _self.onRejectedCallbacks.push(() => onRejected(_self.reason));
       break;
     default:
       break;
   }
   return new _Promise((resolve, reject) => {});
 };

但是,好家伙,then方法现在已经有部分逻辑了,要返回新的_Promise实例的话,应该在哪里插入呢?像上面一样,在最后一行返回吗?肯定不是对吧。我们先用原生的Promise,链式调用下then,感受下then的逻辑:

 const p0 = new Promise((resolve, reject) => {
   setTimeout(() => {
     resolve(1);
   });
 });
 ​
 p0.then((res) => {
   console.log('监听p0 resolved状态的返回值', res);
 }).then((res) => {
   console.log('监听p1 resolved状态的返回值', res);
 });

上述代码输出结果如下:

 监听p0 resolved状态的返回值 1                             
 监听p1 resolved状态的返回值 undefined  

为了方便描述,我们将第一个then里的返回的Promise称为P1,将第二个then里返回的Promise称为P2,最开始new出来的是p0,也就是下面这样:

image-20240910205541118.png

从这里我们可以看出,then里的swich case的逻辑,要放在new _Promise里的:

 _Promise.prototype.then = function (onResolved, onRejected) {
   const _self = this;
   return new _Promise((resolve, reject) => {
     switch (_self.status) {
       case 'resolved':
         onResolved(_self.value);
         // 调用完onResolved之后,根据结果决定是触发 resolve 或者 reject
         break;
       case 'rejected':
         onRejected(_self.reason);
       case 'pending':
         _self.onResolvedCallbacks.push(() => onResolved(_self.value));
         _self.onRejectedCallbacks.push(() => onRejected(_self.reason));
         break;
       default:
         break;
     }
   });
 };

只有这样,我们才能在调用then的第一个参数onResolved或者第二个参数onRejected的时候,触发new _Promiseresolve或者reject,改变返回的_Promise的实例的状态。 对于P1来说,它触发的是case ‘resolved’这个情况,因此会执行onResolved(_self.value), 此时的_selfp0,所以_self.value就是1

接下来,我们根据onResolved(_self.value)的返回结果,决定是触发new _Promiseresolve还是reject 。如果结果没报错,那么就是触发resolve,否则就是触发reject

 _Promise.prototype.then = function (onResolved, onRejected) {
   const _self = this;
   return new _Promise((resolve, reject) => {
     const callback = (result) => {
       try {
         resolve(result);
       } catch (e) {
         reject(e);
       }
     };
 ​
     switch (_self.status) {
       case 'resolved':
         callback(onResolved(_self.value));
         break;
       case 'rejected':
         onRejected(_self.reason);
       case 'pending':
         _self.onResolvedCallbacks.push(() => onResolved(_self.value));
         _self.onRejectedCallbacks.push(() => onRejected(_self.reason));
         break;
       default:
         break;
     }
   });
 };

我们在case 'resolved'的时候,将onResolved(_self.value)的执行结果传到callback函数里,然后在callback里对该结果进行判断,没报错就resolve,报错就reject。 但是,这样是有问题的,我们是把onResolved(_self.value)的结果传到callback里了,而不是整个onResolved的执行过程,如果在执行onResolved的过程中报错了,那并不会进入到callback的逻辑,报错也就不会被callbakc捕捉了,因此,我们需要修改下,将整个onResolved传入到callback中,然后在callback中执行onResolved,这样执行onResolved的过程中报错了才能被try-catch捕捉到。

 _Promise.prototype.then = function (onResolved, onRejected) {
   const _self = this;
   return new _Promise((resolve, reject) => {
     const callback = (fn) => {
       try {
         const result = fn(_self.value); // 执行传入的 onResolved
         resolve(result);
       } catch (e) {
         reject(e);
       }
     };
 ​
     switch (_self.status) {
       case 'resolved':
         callback(onResolved); // 将 onResolved 传入 callback 中
         break;
       case 'rejected':
         onRejected(_self.reason);
       case 'pending':
         _self.onResolvedCallbacks.push(() => callback(onResolved)); // 同样,这里也要将 onResolved 传入 callback 中
         _self.onRejectedCallbacks.push(() => onRejected(_self.reason));
         break;
       default:
         break;
     }
   });
 };

在上述代码中,我们在命中case 'resolved'时将onResolved传入callback,同样,在pending收集onResolvedCallbacks时,也是将onResolved传入到callback中,这样一来,所有onResolved的情况都能被try-catch捕捉了。 同样,对于case 'rejected'的处理也是跟onResolved的一样,也要将onRejected传入callback进行处理。

 _Promise.prototype.then = function (onResolved, onRejected) {
   const _self = this;
   return new _Promise((resolve, reject) => {
     const callback = (fn) => {
       try {
         const result = fn(_self.value || _self.reason);
         resolve(result);
       } catch (e) {
         reject(e);
       }
     };
 ​
     switch (_self.status) {
       case 'resolved':
         callback(onResolved);
         break;
       case 'rejected':
         callback(onRejected);
       case 'pending':
         _self.onResolvedCallbacks.push(() => callback(onResolved));
         _self.onRejectedCallbacks.push(() => callback(onRejected));
         break;
       default:
         break;
     }
   });
 };

这里我们稍微做了下优化,在第6行代码中,将_self.value_self.reason通过或逻辑一起传递给fn了,之所以能这样做,是因为如果传入的是onRejected,执行的就是_Promise()构造函数里的resject方法:

 function _Promise(executor) {
   const _self = this;
   _self.status = 'pending';
   _self.value = undefined; // 保存resolve函数的入参
   _self.reason = undefined; // 保存reject函数的入参
   // 其他代码
   function reject(err) {
     _self.status = 'rejected';
     _self.reason = err;
     // 其他代码
   }
   // 其他代码
 }

此时_self.value肯定是undefined。 同样,反过来如果传入的是onResolved,那么_self.value肯定有值。

4. 修复then状态与onResolved同步的问题

到这一步,我们的then方法的实现就完成90%了,还差10%是没考虑这种情况:如果then返回的Promise里的callback,也就是下面的代码,

 const result = fn(_self.value || _self.reason)

fn的执行结果result如果是一个_Promise对象怎么处理呢? 也就是下面这种情况,我们用原生的Promise看一下输出:

 const p0 = new Promise((resolve, reject) => resolve());
 p0.then((res) => {
   return new Promise((resolve, reject) => reject('p1 的 onResolved 里返回了新的 Promise,其状态是 rejected'));
 }).then(
   (res) => {
     console.log('监听p1 resolved 状态的返回值');
     console.log(e);
   },
   (e) => {
     console.log('监听p1 rejected 状态的返回值');
     console.log(e);
   }
 );

上述代码输出如下:

 监听p1 rejected 状态的返回值                                      
 p1 的 onResolved 里返回了新的 Promise,其状态是 rejected 

根据上述输出,我们可以得知:如果then的第一个参数函数onResolved里返回了新的Promise(称为p1-1),那么then返回的Promise的状态,也就是这里的p1p1的状态是跟p1-1的状态保持一致的。 注意这里有两个返回的Promise,一个是then本身执行结果返回的Promise,一个是then的第一个参数函数onResolved返回的Promise,前者的状态会跟后者保持一致。

然后,我们再换成我们刚实现的_Promise

 const p0 = new _Promise((resolve, reject) => resolve());
 p0.then((res) => {
   return new _Promise((resolve, reject) => reject('p1 的 onResolved 里返回了新的 Promise,其状态是 rejected'));
 }).then(
   (res) => {
     console.log('监听p1 resolved 状态的返回值');
     console.log(res);
   },
   (e) => {
     console.log('监听p1 rejected 状态的返回值');
     console.log(e);
   }
 );

这里有两个new Promise要改成new _Promise:其输出如下:

 监听p1 resolved 状态的返回值                                                                                  
 _Promise {                                                                       
   status: 'rejected',                                             
   value: undefined,                                               
   reason: 'p1 的 onResolved 里返回了新的 Promise,其状态是 rejected',
   onResolvedCallbacks: [],                                                                               
   onRejectedCallbacks: []
 } 

根据输出结果,可以看到它走的是p2onResolved的逻辑,因此p1的状态是resolved,但是p1onResolved里返回的Promise(也就是p1-1)的状态是rejected,也就是说,p1的状态跟p1-1不一致了,then返回的Promise,跟then的入参函数onResolved返回的Promise的状态不一致!! 这是什么原因呢?!我们来看下我们实现的_Promise.prototype.then,重点看callback

 _Promise.prototype.then = function (onResolved, onRejected) {
   const _self = this;
   return new _Promise((resolve, reject) => {
     const callback = (fn) => {
       try {
         const result = fn(_self.value || _self.reason);
         resolve(result);
       } catch (e) {
         reject(e);
       }
     };
   // 其他代码
 };

callback里,我们只是根据fn的执行结果进行resolved了,而没有判断fn返回新的_Promise实例的情况,这就导致我们的then返回的Promise的状态跟then的第一个参数onResolved返回的Promise的状态不一致的原因。 知道了原因,修复起来也就容易了,我们只需要增加一个判断,判断fn的执行结果result是不是_Promise实例,如果是的话,就让then返回的Promise的状态跟该实例的状态保持一致即可。

 _Promise.prototype.then = function (onResolved, onRejected) {
   const _self = this;
   return new _Promise((resolve, reject) => {
     const callback = (fn) => {
       try {
         const result = fn(_self.value || _self.reason);
         if (result instanceof _Promise) {
           result.then((res) => resolve(res), (err) => reject(err));
           return;
         }
         resolve(result);
       } catch (e) {
         reject(e);
       }
     };
   // 省略 switch case 逻辑
 };

这里我们判断如果fn的返回结果result是_Promise实例的话,就在result.then里同步_Promise.prototype.then返回的Promise的状态,注意这里在第9行还加了个return,从而结束函数。 就这一个改动,是不是很简单? 然后,我们再执行以下代码测试一下修改后的then:

 const p0 = new _Promise((resolve, reject) => resolve());
 p0.then((res) => {
   return new _Promise((resolve, reject) => reject('p1 的 onResolved 里返回了新的 Promise,其状态是 rejected'));
 }).then(
   (res) => {
     console.log('监听p1 resolved 状态的返回值');
     console.log(res);
   },
   (e) => {
     console.log('监听p1 rejected 状态的返回值');
     console.log(e);
   }
 );

上述代码执行结果如下:

 监听p1 rejected 状态的返回值                                     
 p1 的 onResolved 里返回了新的 Promise,其状态是 rejected   

奈斯!!!非常好!p1onResolved 里返回了个 rejected 状态的 Promisep1的状态也变成了rejected,两者同步了! 完整代码放在下面给大家了:

 function _Promise(executor) {
   const _self = this;
   _self.status = 'pending';
   _self.value = undefined; // 保存resolve函数的入参
   _self.reason = undefined; // 保存reject函数的入参
   _self.onResolvedCallbacks = []; // 保存pending状态下的onResolved函数
   _self.onRejectedCallbacks = []; // 保存pending状态下的onRejected函数
 ​
   function resolve(res) {
     if (_self.status === 'pending') {
       _self.status = 'resolved';
       _self.value = res;
       // 一旦 resolve 执行,遍历执行已收集到的 onResolved 回调函数,并重置 onResolvedCallbacks
       _self.onResolvedCallbacks.forEach((fn) => fn());
       _self.onResolvedCallbacks = [];
     }
   }
 ​
   function reject(err) {
     if (_self.status === 'pending') {
       _self.status = 'rejected';
       _self.reason = err;
       // 一旦 reject 执行,遍历执行已收集到的 onRejectedCallbacks 回调函数,并重置 onRejectedCallbacks
       _self.onRejectedCallbacks.forEach((fn) => fn());
       _self.onRejectedCallbacks = [];
     }
   }
 ​
   try {
     executor(resolve, reject);
   } catch (e) {
     reject(e);
   }
 }
 ​
 _Promise.prototype.then = function (onResolved, onRejected) {
   const _self = this;
   return new _Promise((resolve, reject) => {
     const callback = (fn) => {
       try {
         const result = fn(_self.value || _self.reason);
         if (result instanceof _Promise) {
           // prettier-ignore
           result.then((res) => resolve(res), (err) => reject(err));
           return;
         }
         resolve(result);
       } catch (e) {
         reject(e);
       }
     };
 ​
     switch (_self.status) {
       case 'resolved':
         callback(onResolved);
         break;
       case 'rejected':
         callback(onRejected);
       case 'pending':
         _self.onResolvedCallbacks.push(() => callback(onResolved));
         _self.onRejectedCallbacks.push(() => callback(onRejected));
         break;
       default:
         break;
     }
   });
 };
 ​
 const p0 = new _Promise((resolve, reject) => resolve());
 p0.then((res) => {
   return new _Promise((resolve, reject) => reject('p1 的 onResolved 里返回了新的 Promise,其状态是 rejected'));
 }).then(
   (res) => {
     console.log('监听p1 resolved 状态的返回值');
     console.log(res);
   },
   (e) => {
     console.log('监听p1 rejected 状态的返回值');
     console.log(e);
   }
 );

以上就是我们Promise以及Promise.prototype.then的实现逻辑,我们实现了Promise的状态的改变、异步处理、then的链式调用以及then的状态与onResolved同步问题。 整个文章逻辑应该是比较清晰的,如果有讲的不清楚或者讲错的地方,欢迎你评论区留言~我看到的话会及时回复的。

以上就是这篇文章的全部内容了,如果对你有帮助的话,还请点个赞或者收藏支持一下吧~

彩蛋

其实我们实现的then还有个小问题,then里的回调函数,是会异步执行的,而我们的then,目前还是同步执行。我们来测试一下:

 const p0 = new Promise((resolve) => {
   console.log(1);
   resolve(3);
 });
 ​
 p0.then((val) => {
   console.log(val);
 });
 ​
 console.log(2);

上述代码正常输出是:1 2 3

image-20240911100349710.png

然后,我们再换成_Promise试试:

 const p0 = new _Promise((resolve) => {
   console.log(1);
   resolve(3);
 });
 ​
 p0.then((val) => {
   console.log(val);
 });
 ​
 console.log(2);

其输出如下:诶?!变成 1 3 2 了?

image-20240911100601784.png

这可咋搞?!

如果你有解决方案的话,也欢迎评论区留言哦,我们会在下篇文章解决这个问题,并继续实现Promisecatchraceall等方法。

下一篇,新手也能看懂的Promise原理,超简单!不来看一下吗?(续)