溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么理解Promise中的core.js

發(fā)布時間:2021-11-17 15:16:28 來源:億速云 閱讀:203 作者:iii 欄目:web開發(fā)

這篇文章主要講解了“怎么理解Promise中的core.js”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“怎么理解Promise中的core.js”吧!

源碼閱讀階段

先理解Promise根本吧,想快點理解的話可以直接跳到下個標(biāo)題.這部分根據(jù)理解將持續(xù)修改。

Promise(fn)

function noop() {} /* 空函數(shù),用于判斷傳入Promise構(gòu)造器的函數(shù)是否為空函數(shù),如果為空函數(shù)構(gòu)造一個promise對象并初始化狀態(tài)為pending,終值null,回調(diào)狀態(tài)0和隊列null. */ var LAST_ERROR = null;//記錄Promise內(nèi)部***的一次錯誤 var IS_ERROR = {}; //空對象,標(biāo)識表示發(fā)生了錯誤 module.exports = Promise; //暴露模塊接口為Promise function Promise(fn) {   if (typeof this !== 'object') {     throw new TypeError('Promises must be constructed via new');   }   if (typeof fn !== 'function') {     throw new TypeError('Promise constructor\'s argument is not a function');   }   this._deferredState = 0;   this._state = 0; //promise狀態(tài)   this._value = null; //resolve返回的結(jié)果   this._deferreds = null;   if (fn === noop) return;   doResolve(fn, this); //處理函數(shù) } Promise._onHandle = null; Promise._onReject = null; Promise._noop = noop;

原文中表示將帶有_前綴的變量在構(gòu)造的時候轉(zhuǎn)為(_隨機數(shù))的形式,來混淆和阻止它們被使用.接下來列出說明重要的變量。

* _defferedState = 0 表示_deferreds的類型,0時表示null,1時表示單個handler(后面講述),2表示多個deferreds(數(shù)組) * _state = 0 promise狀態(tài),0為pending,1為fulfilled,2為rejected,3則為值已被傳遞給下個promise. * _value = null resolve返回的結(jié)果,也就是我們所說的終值/拒因 * _deferreds = null 表示單個或多個handler(后面講述)

doResolve(fn,this)

相比大家都看到這行函數(shù)了doResolve(fn,  this);,這里也就是我們初始化一個Promise時會做的事了,我們在看這個函數(shù)前,先理解下源碼中類似于工具函數(shù)一樣的函數(shù)。

//獲取then方法,沒有then方法標(biāo)識錯誤 function getThen(obj) {   try {     return obj.then;   } catch (ex) {     LAST_ERROR = ex;     return IS_ERROR;   } } //內(nèi)部捕獲錯誤,單個參數(shù)函數(shù) function tryCallOne(fn, a) {   try {     return fn(a);   } catch (ex) {     LAST_ERROR = ex;     return IS_ERROR;   } } //內(nèi)部捕獲錯誤,兩個參數(shù)函數(shù) function tryCallTwo(fn, a, b) {   try {     fn(a, b);   } catch (ex) {     LAST_ERROR = ex;     return IS_ERROR;   } }

接下來我們直接跳到doResolve(fn,promise)處:

function doResolve(fn, promise) {//傳入?yún)?shù)為一個函數(shù),一個promise對象   var done = false; //保證了規(guī)范中提到的一次性   var res = tryCallTwo(fn, function (value) {//看到了么,用于捕獲錯誤.     if (done) return; //這里不用說了,為了保證兩個函數(shù)中只有一個函數(shù)運行且僅運行一次     done = true;     resolve(promise, value);//后續(xù)再分析它   }, function (reason) {     if (done) return;     done = true;     reject(promise, reason);//后續(xù)再分析它   });   if (!done && res === IS_ERROR) {     done = true;     reject(promise, LAST_ERROR);//后續(xù)再分析它   } }

這就是我們的doResolve函數(shù),可以看出,它只是個中間件,用于干什么的呢,就是解決傳入函數(shù)error問題并進行reject的.重點是調(diào)用了我們很眼熟的兩個函數(shù),resolve()和reject()。

resolve() and reject()

在這個函數(shù)里我們找到了兩個新東西,resolve()和reject(),看名字就知道這兩個函數(shù)是什么啦,我們先看reject()吧!

function reject(self, newValue) {//兩個參數(shù),從doResolve我們可以知道self是一個promise對象,而newValue就是拒因啦   self._state = 2;//狀態(tài)變成rejected了   self._value = newValue;//promise中結(jié)果變?yōu)榫芤?nbsp;  if (Promise._onReject) {//在core.js中它為null,所以可能是用于別的功能.我們直接跳過     Promise._onReject(self, newValue);   }   finale(self);//新的函數(shù)又出現(xiàn)了. }

reject()函數(shù)傳入了promise對象和一個reason拒因,函數(shù)做的就是將promise的狀態(tài)變?yōu)閞ejected,并將promise的值進行更改.然后調(diào)用finale()函數(shù)。

可以看到出現(xiàn)了新函數(shù)finale(),并且傳了已經(jīng)進行完reject的promise對象給它.但是我們還是先看resolve()吧!

function resolve(self, newValue) { //這里寫的其實就是按照規(guī)范處理的流程   /* Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure */   if (newValue === self) {//傳入值等于自己就拋出錯誤     return reject(       self,       new TypeError('A promise cannot be resolved with itself.')     );   }   if (//值為對象或函數(shù)     newValue &&     (typeof newValue === 'object' || typeof newValue === 'function')   ) {     var then = getThen(newValue);//獲取值中的then函數(shù)     if (then === IS_ERROR) {//不存在then,reject去       return reject(self, LAST_ERROR);     }     if (//存在并且原來值它是一個promise對象       then === self.then &&       newValue instanceof Promise     ) {//同步兩個promise,將傳入的promise狀態(tài)變?yōu)橐褌鬟f并把newValue這個promise對象作為promise的值,然后finale并退出函數(shù).       self._state = 3;       self._value = newValue;       finale(self);       return;     } else if (typeof then === 'function') {//如果獲取到then的值不為promise,但then是一個函數(shù)(thenable)       doResolve(then.bind(newValue), self);//這里可以看看上個博文,對這個情況有說明,對終值自身進行doResolve取得新的值作為新的終值.       return;     }   }   self._state = 1;//promise狀態(tài)為fulfilled   self._value = newValue;//值傳遞   finale(self);//finale了 }

在resolve()中,我們照樣是傳進了一個promise對象和value(終值),函數(shù)內(nèi)部通過標(biāo)準(zhǔn)的判斷(詳細(xì)參考學(xué)習(xí)筆記(二):規(guī)范),進行[[Resolve]]操作,***將promise對象狀態(tài)變更為fulfilled并改變其終值,調(diào)用finale。

finale()

我們可以進行finale()的分析了,畢竟我們的核心函數(shù)都指向它呢!

function finale(self) {//傳入了一個promise對象   if (self._deferredState === 1) {//判斷deferreds是單個     handle(self, self._deferreds);//傳入了promise對象和promise對象中的_deferreds     self._deferreds = null;//讓deferreds為null   }   if (self._deferredState === 2) {//判斷deferreds是數(shù)組     for (var i = 0; i < self._deferreds.length; i++) {       handle(self, self._deferreds[i]);//傳入了promise對象和promise對象中的_deferreds數(shù)組的所有數(shù)據(jù)     }     self._deferreds = null;//讓deferreds為null   } }

很好,這下都是新的東西了,_deferredState這個就是判斷_deferreds是數(shù)組還是單個的情況,并對其中每一個deferred進行handle調(diào)用.但是_defferreds又是什么呢,handle()這個函數(shù)又做了什么處理呢...

handle()

function handle(self, deferred) {//這個傳入?yún)?shù)是預(yù)想之中的   while (self._state === 3) {//promise狀態(tài)為3的時候,也就是該promise已傳遞完畢的時候     self = self._value;//重定位self為promise傳遞的值   }   if (Promise._onHandle) {//同樣不屬于本篇考慮范疇     Promise._onHandle(self);   }   if (self._state === 0) {//promise狀態(tài)為pending時     if (self._deferredState === 0) {//沒有deferreds時       self._deferredState = 1;//deferreds變?yōu)閱蝹€       self._deferreds = deferred;傳入deferreds入列       return;     }     if (self._deferredState === 1) {       self._deferredState = 2;//deferreds變?yōu)閿?shù)組       self._deferreds = [self._deferreds, deferred];//傳入deferred進入數(shù)組       return;     }     self._deferreds.push(deferred);//已經(jīng)是數(shù)組了就直接push增加     return;   }   handleResolved(self, deferred);//新東西,在state!==0時傳入promise和defered }

可以看到其實這個函數(shù)在對_deferreds進行添加,進行著_deferreds的修改和寫入,與finale()所做的事情恰恰相反,但是詳細(xì)的處理卻還是在handleResolved()函數(shù)里面。

handleResolved()

function handleResolved(self, deferred) {   asap(function() {//注意!asap是一個引入的模塊,意思就是as soon as possible,就是盡快執(zhí)行的意思,我們不需要考慮它做了什么.     // promise狀態(tài)是fulfilled情況下cb為deferred中的Fulfilled函數(shù),不是的話則為onRejected函數(shù)...     var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;     if (cb === null) {//如果不存在對應(yīng)狀態(tài)的函數(shù)       if (self._state === 1) {//當(dāng)前promise對象是否為fulfilled狀態(tài)         resolve(deferred.promise, self._value);//傳入deferred中保存的promise和當(dāng)前promise的值進行resolve       } else {         reject(deferred.promise, self._value);//與上類似,進行reject       }       return;     }     var ret = tryCallOne(cb, self._value);//存在則嘗試執(zhí)行對應(yīng)函數(shù),返回執(zhí)行結(jié)果(與兩個參數(shù)的tryCall不同,這里返回了函數(shù)運行結(jié)果)     if (ret === IS_ERROR) {//有錯誤,reject       reject(deferred.promise, LAST_ERROR);     } else {//沒錯誤,對deferred.promise用函數(shù)返回值進行resolve       resolve(deferred.promise, ret);     }   }); }

這里我們看到了deferred是一個保存了promise對象,onFulfilled函數(shù),onRejected函數(shù)的對象,相當(dāng)于一個保存現(xiàn)場.其實這里就是我們即將在源碼core.js解析(下)寫到的handler對象了.但是這里我們暫且先不深究,知道就好了。

handleResolved()毫無疑問就是在進行著promise的終值傳遞處理,對舊promise對象的狀態(tài)修改,并調(diào)用resolve和reject獲取到值/拒因向下一個Promise傳遞.對這里的詳細(xì)實例分析我們放到(下)來講。

構(gòu)造一個Promise時發(fā)生了啥?

從簡單看起,我們構(gòu)造一個Promise對象的時候經(jīng)過了哪些函數(shù)。

先理一下思路。

var A = Promise(function(resolve,reject){     resolve("ok"); })

這里面首先是先構(gòu)造了Promise對象,我們稱為A,在構(gòu)造階段執(zhí)行了如下代碼。

檢查略....

A._deferredState = 0; A._state = 0; A._value = null; A._deferreds = null;

檢查傳入?yún)?shù)不為空....

doResolve(function(resolve,reject){     resolve("ok"); },this);

然后我們跳到了doResolve()函數(shù)處,傳入為fn,promise

res = tryCallTwo(fn,function(value){resolve(promise, value);},function(reason){reject(promise, reason);}); 出錯就reject(promise,LAST_ERROR)

出錯就reject(promise,LAST_ERROR)

我們又根據(jù)我們的輸入跳轉(zhuǎn)到了resolve(promise,value)啦,這里理一下我們的函數(shù),promise就是A,value其實就是我們傳入的"ok"。

所以執(zhí)行的是promise內(nèi)部中的resolve(promise,"ok")

經(jīng)過一系列判斷(詳細(xì)可以看規(guī)范),我們的"ok"過五關(guān)斬六將直接執(zhí)行到這一步。

self._state = 1;//A狀態(tài)變?yōu)閒ulfilled self._value = newValue;//AA終值變?yōu)?quot;ok"

然后我們finale(self)啦,繼續(xù)跳到finale()函數(shù),傳入了A.

//在過程中我們的_deferredState始終為0呀,看了一下 A._deferredState = 0; //已經(jīng)沒有什么好做的了...

感謝各位的閱讀,以上就是“怎么理解Promise中的core.js”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對怎么理解Promise中的core.js這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI