成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Promise學習筆記(三):源碼core.js解析(上)

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

[[171859]]

源碼閱讀階段

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

Promise(fn) 

  1. function noop() {} 
  2. /* 
  3. 空函數,用于判斷傳入Promise構造器的函數是否為空函數,如果為空函數構造一個promise對象并初始化狀態為pending,終值null,回調狀態0和隊列null
  4. */ 
  5. var LAST_ERROR = null;//記錄Promise內部***的一次錯誤 
  6. var IS_ERROR = {}; //空對象,標識表示發生了錯誤 
  7. module.exports = Promise; //暴露模塊接口為Promise 
  8. function Promise(fn) { 
  9.   if (typeof this !== 'object') { 
  10.     throw new TypeError('Promises must be constructed via new'); 
  11.   } 
  12.   if (typeof fn !== 'function') { 
  13.     throw new TypeError('Promise constructor\'s argument is not a function'); 
  14.   } 
  15.   this._deferredState = 0; 
  16.   this._state = 0; //promise狀態 
  17.   this._value = null; //resolve返回的結果 
  18.   this._deferreds = null
  19.   if (fn === noop) return
  20.   doResolve(fn, this); //處理函數 
  21. Promise._onHandle = null
  22. Promise._onReject = null
  23. Promise._noop = noop;  

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

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

doResolve(fn,this)

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

  1. //獲取then方法,沒有then方法標識錯誤 
  2. function getThen(obj) { 
  3.   try { 
  4.     return obj.then
  5.   } catch (ex) { 
  6.     LAST_ERROR = ex; 
  7.     return IS_ERROR; 
  8.   } 
  9. //內部捕獲錯誤,單個參數函數 
  10. function tryCallOne(fn, a) { 
  11.   try { 
  12.     return fn(a); 
  13.   } catch (ex) { 
  14.     LAST_ERROR = ex; 
  15.     return IS_ERROR; 
  16.   } 
  17. //內部捕獲錯誤,兩個參數函數 
  18. function tryCallTwo(fn, a, b) { 
  19.   try { 
  20.     fn(a, b); 
  21.   } catch (ex) { 
  22.     LAST_ERROR = ex; 
  23.     return IS_ERROR; 
  24.   } 
  25.  

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

  1. function doResolve(fn, promise) {//傳入參數為一個函數,一個promise對象 
  2.   var done = false; //保證了規范中提到的一次性 
  3.   var res = tryCallTwo(fn, function (value) {//看到了么,用于捕獲錯誤. 
  4.     if (done) return; //這里不用說了,為了保證兩個函數中只有一個函數運行且僅運行一次 
  5.     done = true
  6.     resolve(promise, value);//后續再分析它 
  7.   }, function (reason) { 
  8.     if (done) return
  9.     done = true
  10.     reject(promise, reason);//后續再分析它 
  11.   }); 
  12.   if (!done && res === IS_ERROR) { 
  13.     done = true
  14.     reject(promise, LAST_ERROR);//后續再分析它 
  15.   } 
  16.  

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

resolve() and reject()

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

  1. function reject(self, newValue) {//兩個參數,從doResolve我們可以知道self是一個promise對象,而newValue就是拒因啦 
  2.   self._state = 2;//狀態變成rejected了 
  3.   self._value = newValue;//promise中結果變為拒因 
  4.   if (Promise._onReject) {//在core.js中它為null,所以可能是用于別的功能.我們直接跳過 
  5.     Promise._onReject(self, newValue); 
  6.   } 
  7.   finale(self);//新的函數又出現了. 
  8.  

reject()函數傳入了promise對象和一個reason拒因,函數做的就是將promise的狀態變為rejected,并將promise的值進行更改.然后調用finale()函數。

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

  1. function resolve(self, newValue) { 
  2. //這里寫的其實就是按照規范處理的流程 
  3.   /* Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure */ 
  4.   if (newValue === self) {//傳入值等于自己就拋出錯誤 
  5.     return reject( 
  6.       self, 
  7.       new TypeError('A promise cannot be resolved with itself.'
  8.     ); 
  9.   } 
  10.   if (//值為對象或函數 
  11.     newValue && 
  12.     (typeof newValue === 'object' || typeof newValue === 'function'
  13.   ) { 
  14.     var then = getThen(newValue);//獲取值中的then函數 
  15.     if (then === IS_ERROR) {//不存在then,reject去 
  16.       return reject(self, LAST_ERROR); 
  17.     } 
  18.     if (//存在并且原來值它是一個promise對象 
  19.       then === self.then && 
  20.       newValue instanceof Promise 
  21.     ) {//同步兩個promise,將傳入的promise狀態變為已傳遞并把newValue這個promise對象作為promise的值,然后finale并退出函數. 
  22.       self._state = 3; 
  23.       self._value = newValue; 
  24.       finale(self); 
  25.       return
  26.     } else if (typeof then === 'function') {//如果獲取到then的值不為promise,但then是一個函數(thenable) 
  27.       doResolve(then.bind(newValue), self);//這里可以看看上個博文,對這個情況有說明,對終值自身進行doResolve取得新的值作為新的終值. 
  28.       return
  29.     } 
  30.   } 
  31.   self._state = 1;//promise狀態為fulfilled 
  32.   self._value = newValue;//值傳遞 
  33.   finale(self);//finale了 
  34.  

在resolve()中,我們照樣是傳進了一個promise對象和value(終值),函數內部通過標準的判斷(詳細參考學習筆記(二):規范),進行[[Resolve]]操作,***將promise對象狀態變更為fulfilled并改變其終值,調用finale。

finale()

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

  1. function finale(self) {//傳入了一個promise對象 
  2.   if (self._deferredState === 1) {//判斷deferreds是單個 
  3.     handle(self, self._deferreds);//傳入了promise對象和promise對象中的_deferreds 
  4.     self._deferreds = null;//讓deferreds為null 
  5.   } 
  6.   if (self._deferredState === 2) {//判斷deferreds是數組 
  7.     for (var i = 0; i < self._deferreds.length; i++) { 
  8.       handle(self, self._deferreds[i]);//傳入了promise對象和promise對象中的_deferreds數組的所有數據 
  9.     } 
  10.     self._deferreds = null;//讓deferreds為null 
  11.   } 
  12.  

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

handle() 

  1. function handle(self, deferred) {//這個傳入參數是預想之中的 
  2.   while (self._state === 3) {//promise狀態為3的時候,也就是該promise已傳遞完畢的時候 
  3.     self = self._value;//重定位self為promise傳遞的值 
  4.   } 
  5.   if (Promise._onHandle) {//同樣不屬于本篇考慮范疇 
  6.     Promise._onHandle(self); 
  7.   } 
  8.   if (self._state === 0) {//promise狀態為pending時 
  9.     if (self._deferredState === 0) {//沒有deferreds時 
  10.       self._deferredState = 1;//deferreds變為單個 
  11.       self._deferreds = deferred;傳入deferreds入列 
  12.       return
  13.     } 
  14.     if (self._deferredState === 1) { 
  15.       self._deferredState = 2;//deferreds變為數組 
  16.       self._deferreds = [self._deferreds, deferred];//傳入deferred進入數組 
  17.       return
  18.     } 
  19.     self._deferreds.push(deferred);//已經是數組了就直接push增加 
  20.     return
  21.   } 
  22.   handleResolved(self, deferred);//新東西,在state!==0時傳入promise和defered 
  23.  

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

handleResolved() 

  1. function handleResolved(self, deferred) { 
  2.   asap(function() {//注意!asap是一個引入的模塊,意思就是as soon as possible,就是盡快執行的意思,我們不需要考慮它做了什么. 
  3.     // promise狀態是fulfilled情況下cb為deferred中的Fulfilled函數,不是的話則為onRejected函數... 
  4.     var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; 
  5.     if (cb === null) {//如果不存在對應狀態的函數 
  6.       if (self._state === 1) {//當前promise對象是否為fulfilled狀態 
  7.         resolve(deferred.promise, self._value);//傳入deferred中保存的promise和當前promise的值進行resolve 
  8.       } else { 
  9.         reject(deferred.promise, self._value);//與上類似,進行reject 
  10.       } 
  11.       return
  12.     } 
  13.     var ret = tryCallOne(cb, self._value);//存在則嘗試執行對應函數,返回執行結果(與兩個參數的tryCall不同,這里返回了函數運行結果) 
  14.     if (ret === IS_ERROR) {//有錯誤,reject 
  15.       reject(deferred.promise, LAST_ERROR); 
  16.     } else {//沒錯誤,對deferred.promise用函數返回值進行resolve 
  17.       resolve(deferred.promise, ret); 
  18.     } 
  19.   }); 
  20.  

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

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

構造一個Promise時發生了啥?

從簡單看起,我們構造一個Promise對象的時候經過了哪些函數。

先理一下思路。

  1. var A = Promise(function(resolve,reject){ 
  2.     resolve("ok"); 
  3. })  

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

檢查略.... 

  1. A._deferredState = 0; 
  2. A._state = 0; 
  3. A._value = null
  4. A._deferreds = null 

檢查傳入參數不為空.... 

  1. doResolve(function(resolve,reject){ 
  2.     resolve("ok"); 
  3. },this); 

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

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

出錯就reject(promise,LAST_ERROR)

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

所以執行的是promise內部中的resolve(promise,"ok")

經過一系列判斷(詳細可以看規范),我們的"ok"過五關斬六將直接執行到這一步。

  1. self._state = 1;//A狀態變為fulfilled 
  2. self._value = newValue;//AA終值變為"ok"  

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

  1. //在過程中我們的_deferredState始終為0呀,看了一下 
  2. A._deferredState = 0; 
  3. //已經沒有什么好做的了...  

我們的構造已經結束了!這就是我們new 一個Promise時的過程,跟著思路走,其實加上reject也是同樣的路線而已。

(上)結語

(下)的話我打算重點寫剩余部分的then函數流程,并盡量用簡單的語言來描述,希望自己能進一步理解promise,發現有錯漏能及時修訂。

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2016-09-20 10:26:25

LaravelPHPMiddleware

2016-09-20 10:15:49

LaravelPHPContainer

2011-08-09 17:21:37

2009-06-17 14:21:39

core java

2010-06-12 13:08:51

UML全稱

2010-07-27 15:42:18

AdobeFlex

2020-07-29 17:35:08

Promise源碼前端

2016-12-15 09:44:31

框架Caffe源碼

2010-06-28 15:41:17

UML圖類型

2010-06-28 18:44:54

UML對象圖

2011-09-01 14:14:00

jQuery Mobi

2010-06-13 12:49:23

UML及建模

2021-11-08 15:04:47

鴻蒙HarmonyOS應用

2012-02-23 11:06:18

JavaPlay FramewPlay!

2011-07-18 15:20:28

Core Services 框架

2010-06-30 10:30:29

UML動態建模

2010-07-12 15:16:29

UML關聯

2011-03-30 17:32:28

androidmaniAndroid開發

2011-08-29 10:01:27

QTWebkit插件

2021-09-04 23:27:58

Axios源碼流程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品视频在线观看视频 | 久久在线精品 | а_天堂中文最新版地址 | 黄色网毛片 | 亚洲国产在 | 国产小视频在线观看 | 欧美精品一二三区 | 日韩欧美二区 | 天天看天天干 | 日韩精品一区二区三区中文在线 | 7777久久 | 久久综合国产 | av免费网址| 欧美在线a | 精品国产伦一区二区三区观看方式 | av网站观看 | 一区二区三区在线观看视频 | 成人网在线看 | 日韩理论电影在线观看 | 久久久av一区 | 精品日韩一区 | 欧美久久久久 | 成人久久久 | 国产东北一级毛片 | 精品人伦一区二区三区蜜桃网站 | 亚洲国产精品一区二区第一页 | 91久色| 欧美一级毛片久久99精品蜜桃 | 99精品视频在线观看免费播放 | 碰碰视频 | 国产精品美女久久久久久免费 | 永久免费av| 欧美一级做性受免费大片免费 | 亚洲日本乱码在线观看 | 亚洲国产精品一区二区三区 | 成人在线精品 | 一级黄色毛片a | 日本精品视频在线观看 | 操视频网站 | 黑人久久 | 国产精品久久久久久妇女 |