JavaScript

手写PromiseA+规范的Promise代码

字数:2889    阅读时间:15min
阅读量:19

什么是Promise和Promise A+

Promise是一种异步编程解决方案,比传统的解决方案(回调函数和事件),更合理和更强大。主要解决了回调地狱的问题。它最早是由社区提出和实现,后来ES6 将其统一规范( Promise A+规范 ),写进了标准语法,提供了原生的Promise对象。

Promise的特点:

1、Promise有三种状态(pending(进行中),fulfilled(成功),rejected(失败))。三种状态只能由pending变为fulfilled或者rejected,而且状态一旦发生改变就会凝固,无法再次改变。而且Promise的状态是不受外部影响的, 只有异步操作的结果,才可以决定当前是哪一种状态,任何其他操作都无法改变这个状态 。

2、可以使用then、catch、finally原型方法,链式调用依次执行异步操作,还有一系列静态方法如:resolve,reject,all, race ,any,allSettled。

接下来手写实现符合Promise A+的Promise对象。第四步的then边界处理有点麻烦有时间可以深入研究。

一、实现Promise内部方法resolve、reject,以及Promise状态转换。

二、实现then方法。

promise的then方法是promise的核心重要方法,为更加清晰的理解它的实现方式。我们分三步实现。1、实现基本的then方法调用,并支持异步调用。2、实现then方法的链式调用。3、为then方法添加更加丰富全面的边界处理。

1、实现then方法的基本调用,并支持异步调用。

前言:then方法是有两个回调参数的一个是onFulfilled成功回调,一个是 onRejected失败的回调。注意当前的失败回调onRejected,只能处理当前实例的失败(reject)的情况,而我们的catch可以捕获任何报错。

实现then的基本调用:我们的then方法是调用我们的myProimse类的公共方法,所以直接在类里面写方法就可以。 前面我们已经实现了内部resolve,reject方法,在我们调用resolve、reject方法的时候,会改变当前实例的value、reason和状态。所以在我们就可以在then方法里直接判断状态(fulfilled,rejected),然后执行对应的回调(onFulfilled、 onRejected ),再然后把当前实例的值(value或者reason)传进去就可以。

实现then方法的异步调用:promise的异步调用是隔段时间调用resolve、reject内部方法,如果我们把需要执行的代码(then方法里的回调函数onFulfilled、 onRejected)放在reslove、reject内部函数里面执行,那么我们在一段时间之后调用resolve、reject方法就可以调用到异步的代码,这样就可以实现异步效果了。又因为我们的then可能会执行好几个,所以我们需要执行的回调会有好几个,我们可以写在数组里onReslovedCallbacks(成功回调数组)、onRejectedCallbacks(失败回调数组),在执行resolve、reject方法时分别调用onReslovedCallbacks、 onRejectedCallbacks数组里的所有方法。对了在我们使用了异步方法之后,由于我们还没有执行resolve,reject方法,其实我们的promise的状态是pending的,所以我们需要判断状态是pending的时候再执行上面操作。

2、实现then方法的链式调用。

promise想要链式调用,需要满足两个条件:1、then的返回值是一个promise。2、下一个then能拿到上一个then的返回值。所以我们需要改造一下then方法,让他返回一个promise,并把当前then需要返回的值传递出去作为第二个then的参数。

3、为then方法添加更加丰富全面的边界处理。

通过上面的步骤我们基本上就实现了promise最核心的then方法。但是还有一些边界值的处理需要我们完善一下。因为边界处理会有很多种情况,我们需要将他们放在一个独立函数中;在我们使用边界处理函数的时候,需要传入当前实例,又因为调用的方法就在当前实例里面,所以我们需要用到setTimeout将其转为异步,这样就可以拿到当前实例和返回值进行比较了。

三、实现catch、finally方法

catch方法和then方法一样直接写在myPromise里面。其实then方法很简单,就是then的一个语法糖, 就是调用then方法仅传一个失败处理函数 。finally与catch一样也是then的一个语法糖,不管myPromise是成功或者失败都会执行该回调。

四、实现promise静态方法 Promise.resolve、Promise.reject

Promise的静态方法就是可以用Promise直接调用的方法。我们前面写的resolve、reject方法是Promise的内部方法,他们只能在Promise内部使用。我们在写静态方法的时候直接调用内部方法就行

五、实现promise静态方法 Promise. race、Promise. all

Promise的race、all方法是Promise处理多个Promise的方法。Promise. race:只要有一个Promise的状态发生改变,当前就Promise状态就随之发生改变,可以理解为一个竞速原则。Promise.all:当所有Promise状态都改变了,当前Promise状态才发生改变(所有Promise都返回成功才成功,否则就是失败)

六、实现promise静态方法 Promise. allSettled 、Promise.any

Promise的allSettled方法和any方法跟all、race方法很像。 Promise. allSettled:当所有的promise完成时(不管成功或者失败),当前promise实例就会成功(注意他没有失败catch);需要对所有promise进行遍历,每一个promise都完成时,将每个对象的结果作为一个对象传递出去。Promise.any:当有一个promise成功时当前promise实例就显示成功的结果,所有promise失败时就显示失败的结果数组,也需要遍历所有promise拿到结果

野生小园猿
励志做一只遨游在知识海洋里的小白鲨
查看“野生小园猿”的所有文章 →

发表评论

邮箱地址不会被公开。

相关推荐