You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionPromise(fn){// 判断 this一定得是object不然就会报错,这个方法一定得要new出来if(typeofthis!=='object'){thrownewTypeError('Promises must be constructed via new');}// 判断fn 一定得是一个函数if(typeoffn!=='function'){thrownewTypeError('Promise constructor\'s argument is not a function');}this._deferredState=0;this._state=0;this._value=null;this._deferreds=null;if(fn===noop)return;// 最终doResolve很关键doResolve(fn,this);}
/** * Take a potentially misbehaving resolver function and make sure * onFulfilled and onRejected are only called once. * * Makes no guarantees about asynchrony. */// // 确保`onFulfilled`和`onRejected`方法只调用一次// 不保证异步functiondoResolve(fn,promise){vardone=false;varres=tryCallTwo(fn,function(value){// 如果done 为true 则returnif(done)return;done=true;// 回调执行 resolve()resolve(promise,value);},function(reason){// 如果done 为true 则returnif(done)return;done=true;reject(promise,reason);});// res为truCallTwo()的返回值// 如果done没有完成 并且 res 是 `IS_ERROR`的情况下// 也会执行reject(),同时让done完成if(!done&&res===IS_ERROR){done=true;reject(promise,LAST_ERROR);}}
前言
then/promise
项目是基于Promises/A+
标准实现的Promise
库,从这个项目当中,我们来看Promise
的原理是什么,它是如何做到的,从而更加熟悉Promise
分析
从index.js当中知道,它是先引出了
./core.js
,随后各自执行了其他文件的代码,通过requeire
的方法。我们首先先想一下最基础的promise用法
Promise中的标准
标准中规定:
Pending
,在被resolve
或reject
时,状态变为Fulfilled
或Rejected
resolve
接收成功的数据,reject
接收失败或错误的数据Promise
对象必须有一个then
方法,且只接受两个可函数参数onFulfilled
、onRejected
index.js
我们先看
src/core.js
Promise
是一个构造方法,开始时,它进行了校验,确保了fn
是一个函数,随后对一些变量进行了初始化,最后执行了doResolve()
我们接着看
doResolve
这个方法。doResolve
最关键的是执行了tryCallTwo
方法,这个方法的第二,第三个参数都是回调,当执行回调后,done
为true,同时各自会执行resolve()
或者reject()
方法。最后当tryCallTwo
的返回值为IS_ERROR
时,也会执行reject()
方法。我们先来看一下
tryCallTwo
方法fn
实际就是Promise
初始化时的匿名函数(resolve, reject) => {}
,a
,b
则代表的是resolve()
和reject()
方法,当我们正常执行完promise
函数时,则执行的是resolve
则在doResolve中
,我们当时执行的第二个参数被回调,如果报错,reject()
被执行,则第二个参数被回调。最后捕获了异常,当发生了报错时,会return IS_ERROR
,非报错时会return undinfed
再回到刚才的
doResolve
方法,当执行了第二个参数的回调之后,会执行resolve
方法在没有链式调用
then
的情况下(也就是只要一个then
)的情况下,会将内部状态_state
设置成3
,将传入值赋给内部变量_value
最后会执行final()
方法,不然则会使用doResolve
来调用then
我们再来看下
reject
在
reject
当中我们的_state
变更为了2,同样最后finale
被调用。我们来看下
finale
函数在该方法当中根据不同的
_deferredState
,会执行不同的handle
方法。我们再来看
handle
方法这里比较关键的应该就是通过
deferredState
不同的状态,将deferred
放入deferreds
当中。另外当我们的_state
不为0
时,最终会执行handleResolved
。继续看
handleResolve()
方法在这个方法当中,会根据我们任务(_state)的不同状态,来执行
onFulfilled
或者onRejected
方法。当此方法调用时,也就是我们一个简单的Promise
的结束。回到刚才说的
Promise
构造方法结束的时候设置了
Promise
函数的一些变量随后在
Promise
的原型上设置了then
方法。在
then
这个方法中首先判断了它是否由Promise
构造的,如果不是,则返回并执行safeThen
,不然则执行Promise
构造一个res
对象,然后执行handle
方法,最后将promise
变量res
返回。handle
方法之前有提过,在这里,当初始化时_state
和_deferred
的转改都为0
,因此它会将defrred
保存到promise
当中。先看一下上面说的
safeThen
方法流程
需要有一个
Promise
的构造方法,这个构造方法最终会执行它的参数(resolve, reject) => {}
,声明的then
方法会通过handle()
方法将onFulfilled
和onRejected
方法保存起来。当在外部调用resolve
或者onRejected
时,最终也会执行handle
但是它,会最后根据状态来执行onFulfilled
或者onRejected
。从而到我们的then
回调中。Promise的扩展
done
对
done
的扩展在src/done.js
当中内部执行了
then()
finally
对
finally
的扩展在src/finally.js
当中在
Promise
的标准当中,本身是没有finally
方法的,但是在ES2018
的标准里有,finally
的实现如下Promise
的onFulfilled
和onRejected
不管回调的哪个,最终都会触发callback
回调。还要注意的一点是finally
的返回也是一个Promise
。es6-extensions.js
在
es6-extensions.js
文件当中包含了ES6的一些扩展。Promise.resolve
Promise.reject
Promise.all
Promise.all()
返回的也是一个Promise
函数。内部有一个
remaining
变量每当执行完一个promise
函数后就会减一,当所有promise
执行完,会执行自己的resolve
。Promise.race
遍历传入的
promise
数组,经过Promise.resolve(value)
的源码可以看到,如果value
是一个Promise
则户直接将这个value
返回,最后数组中的promise
哪个优先回调即执行。Promise.property.catch
catch
在标准当中也是没有,虽然我们用的比较多catch
的回调实际是then(null, onRejected)
的回调。广而告之
本文发布于薄荷前端周刊,欢迎Watch & Star ★,转载请注明出处。
欢迎讨论,点个赞再走吧 。◕‿◕。 ~
The text was updated successfully, but these errors were encountered: