按照这些步骤实现和理解promise真的很简单

1.前言

手写一版promise不仅仅是为了面试什么的,了解了基本的实现机制,在工作使用中也会更加得心应手。在看了手写promise的博客以后,第一感觉就是太长,代码太多不想看。我想大多数同学肯定也像我一样看到第一眼可能就被劝退了,或者狠下心想认真看完,到最后发现一知半解。。。
不要再犹豫了,相信我,看什么看几遍都不如自己从头到尾的实现一遍记忆深刻,一遍不够那么就两遍,总有一遍能让你有到豁然开朗的感觉。可能有的小伙伴看到这里又想溜了。但我只是给大家梳理一下手写的流程,具体理解还要靠大家多手敲啊!!
(点我)为了在博客更加清晰,具体代码(带注释)大家可以点击对照练习

2.准备工作
1.须知

1)想实现一个东西的原理的前提是,你很了解他,知道他的所有特征,不然的话你连他是做什么的,怎么用都不知道,又何谈实现呢,所以如果对promise不熟悉的话还是先不建议手写。

2)要开始写代码之前要先想清楚promise的所有的方法,以及使用方法,然后再搭建架子,一步步实现。

3)我们知道promise使用时都是当做一个类,或者说一个构造函数使用的,并且还存在很多静态方法和原型上的方法,比如原型上的 thencatch,类上的静态方法比如 resolverejectallreace

4)所以我们的按照ES5的写法搭建基本架子就如下:

2.搭建架子
(function () {
        // promise 就是构造函数
        // new Promise((resolve,reject)=>{.....})
        const PENDING = 'pending'; // 定义维护的状态机
        const REJECTED = 'rejected';
        const RESOLVED = 'resolved';
        function Promise(excutor) {
            this.status = PENDING;
            this.data = undefined;
            this.callbacks = []; // 用来存储回调函数 {onResolved,onRejected}
        }
        
        Promise.prototype.then = function (onResolved, onRejected) { // 传入两个会回调
        }
        
        Promise.prototype.catch = function (onRejected) {
        }
        
        Promise.resolve = function (value) {
        }
        
        Promise.reject = function (reason) {
        }
        
        Promise.all = function (promises) {
        }
        
        Promise.reace = function (promises) {
        }
    })()
3.逐个突破
1.resolve,reject

1)我们根据一般的使用习惯进行逐步的实现,在使用时我们一般都是通过new Promise() 传入一个执行函数,执行通过调用执行函数的参数方法来改变状态,并且执行then中的回调。所以在这个过程中最重要的部分就是传来的 resolvereject 这两个函数了。

2)首先要理解这两个函数的作用,第一就是改变状态,第二就是执行回调,并且状态只能改变一次,以resolve为例。reject同理。

	 if (this.status !== PENDING) {
	      return;
	  }
	  this.status = RESOLVED;
	  this.data = value; // 存储value值
	  if (this.callbacks.length > 0) {
	      setTimeout(() => {
	          this.callbacks.forEach(callbacksObj => {
	              callbacksObj.onResolved(value);
	          });
	      });
	  }
	  // 我这里将then回调函数存储为对象的形式了
	  // {onResolved(){},onRejected(){}} 然后遍历执行

3)这里需要理解的就是这个this.data = value;,为什么需要存储这个值呢?不是调用resolve(value)的时候传入value就可以直接传给onResolved(value)了吗?

因为promise执行函数可能是同步的,比如:

new Promise((reslove,reject)=>{
    reslove(1);
}).then(value=>{
    console.log(value)
})

这时当执行reslove的时候,还没有执行到then() 也就是说还没有回调函数被存储。那到时候回调函数想执行的时候value从哪里获取呢?这时这个data就出场了

2.接下来就是then方法的实现了

1)then方法是整个promise实现中比较难理解的部分,难理解就在于它的链式传递和它返回值为promise的问题,如果理解了这两个部分,实现起来还是比较容易

2)在实现时我们首先要知道then方法的使用规则,首先then() 传入两个回调,一个成功的回调,一个失败的回调,并且可以链式调用,也就是说可以then(()=>{},()=>{}).then(()=>{},()=>{}) 如此调用下去,之所以可以是因为then方法返回的是promise。

3)既然返回的是promise那就有成功和失败的状态,此promise的状态取决于,回调函数的返回值

let p = new Promise((reslove, reject) => {
    reslove();
});

如果then返回promise 那么then方法的成功与否取决于此promise

p.then(value => {
    return Promise.resolve(1)
}).then(value => {
    console.log(value);
}); // 打印为 1

如果为值类型,返回什么就是成功的并且成功的value为此返回值,不返回也是成功的,只不过值为undefined

p.then(value => {
    return 1;
}).then(value => {
    console.log(value)
}); // 打印为 1 说明是成功的
p.then(value => {
    console.log('不返回')
}).then(value => {
    console.log(value)
}); // 打印为 undefined

如果then中抛出异常,那么这个then返回的promise就是失败的。

p.then(value => {
    throw new Error();
}).then(value => {
},reason => {
    console.log("出错了!")
}); // 打印为 出错了!

4)接下来需要主要的就是如果then( ),传递的两个回调函数不为函数类型如何处理

let p = Promise.resolve(2)
p.then(12,()=>{}).then(value => {
    console.log(value)
}); // 输出为2 

可以看到,既然可以把value传递给下一个then,说明这个不为函数的回调一定是被处理为了 value => value 也就是封装成了一个返回value的函数,我们又知道如果返回值类型,相当于返回了一个Promise.resolve(value)

5)所以then的架子就是

Promise.prototype.then = function (onResolved, onRejected) { // 传入两个会回调
    // 如果为值类型也是会继续传递的
    onResolved = typeof onResolved === 'function' ? onResolved : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
    // 返回的promise
    return new Promise((resolve, reject) => {
        if (this.status === PENDING) {
            this.callbacks.push({
                onResolved(value) {
                // 写用来判断返回的promise成功与否的逻辑
                },
                onRejected(reason) {
                // 写用来判断返回的promise成功与否的逻辑
                }
            })
        } else if (this.status === RESOLVED) { 
        //  在执行函数为同步函数的话,因为resolve执行时的时候没有callback函数 
        // 所以到这里then方法就要直接执行 
        // 此时value从哪里获取呢 就是上面的this.data
            setTimeout(() => {
                // 写用来判断返回的promise成功与否的逻辑
            });
        } else { // 状态为rejected
            setTimeout(() => {
				// 写用来判断返回的promise成功与否的逻辑
            });
        }
    })
}

判断promise的成功与否的逻辑我那一个举例,其他都一致

 else if (this.status === RESOLVED) { // 就相当于resolve的作用 因为resolve的时候没有callback函数 所以到这里要直接执行
 setTimeout(() => {
     try {
         const result = onResolved(this.data);
         if (result instanceof Promise) { // 判断如果为promise类型,那么状态就有此promise决定
             result.then(
                 value => resolve(value),
                 reason => reject(reason)
             )
         } else { // 如果为普通值类型
             resolve(result);
         }
     } catch (error) { // 如果报错
         reject(error)
     }
 });
3.catch

实现了then catch就简单多了,直接复用逻辑

Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}
4.静态方法 resolve 、 reject

这里比较简单,就直接相当于工厂方法,返回一个成功的Promise实例,或者失败的Promise实例就好了。
以reject为例

Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    })
}
5. all 、reace

这两个方法也比较容易,首先要明确的就是,他们返回的都是Promise,并且Promise的成功与失败由数组中的promise决定。

以all方法为例:只需记录当前成功的数量,如果为传入数组的长度就返回成功,否则有失败就为失败。

  Promise.all = function (promises) {
      const values = [];
      let count = 0; // 记录成功的个数
      return new Promise((reslove, reject) => {
          promises.forEach(peomise => {
              peomise.then((value) => {
                  values.push(values);
                  count++;
              }, (reason) => {
                  reject(reason)
              });
          });
          if (count === promises.length) {
              reslove(values)
          }
      })
  }
6.结束语

到这里我们的promise就结束了,我希望同学们可以按照心里的这个框架,随便找一个写好的跟着写几遍,或者跟着我的写几遍,相信你一定可以理解的很透彻。

如果有错误还请及时指出,以免误解其他同学,以上仅为个人感受,如果有更好的学习方法还请多交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木木林_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值