原文鏈接:鏈接
1 最簡單一個案例function runAsync(){ let p = new Promise(function(resolve,reject){ console.log("exec"); setTimeout(function(){ resolve("someData"); },2000); }); return p; } var promise = runAsync(); promise.then(function(data){ console.log(data); }); console.log("同步執行"); console.log(promise);
控制臺輸出
exec 同步執行 Promise //兩秒后 someData2 Promise內部是如何運行的? 2.1 執行這行代碼的時候:let p = new Promise(f);
function noop() {} 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; this._value = null; this._deferreds = null; //注意這里,如果fn傳入的是noop這個函數,那么不會執行doResolve if (fn === noop) return; doResolve(fn, this); } Promise._onHandle = null; Promise._onReject = null; Promise._noop = noop; function doResolve(fn, promise) { var done = false; var res = tryCallTwo(fn, function (value) { if (done) return; done = true; resolve(promise, value); }, function (reason) { if (done) return; done = true; reject(promise, reason); }); if (!done && res === IS_ERROR) { done = true; reject(promise, LAST_ERROR); } } function tryCallTwo(fn, a, b) { try { fn(a, b); } catch (ex) { LAST_ERROR = ex; return IS_ERROR; } }
可以看到 let p = new Promise( f );在 傳入的 f. 函數不是noop的時候,
第一會先執行 f 函數
第二生成一個Promise對象
p =>{ _deferredState:0,//deffer的狀態,代表的應該是 _deferreds 的類型,1 是 single,2 是 Array _state:0,//每個promise對象的狀態維護標識 _value:null,//resolve函數執行的時候,異步得到的結果 _deferreds:null }2.2執行這行代碼的時候: promise.then(function(data){ console.log(data);});
Promise.prototype.then = function(onFulfilled, onRejected) { if (this.constructor !== Promise) {//這些比較的都是引用地址; return safeThen(this, onFulfilled, onRejected); } var res = new Promise(noop); handle(this, new Handler(onFulfilled, onRejected, res)); //注意這里 then的鏈式調用,每次then函數執行完畢之后,返回值都是一個新的Promise實例對象, return res; }; //這里生成一個deffer對象,保存then函數中注冊的onFulfilled和onRejected回調,以及要返回的新的promise實例對象 function Handler(onFulfilled, onRejected, promise){ this.onFulfilled = typeof onFulfilled === "function" ? onFulfilled : null; this.onRejected = typeof onRejected === "function" ? onRejected : null; this.promise = promise; } function handle(self, deferred) { //不會進入這里 while (self._state === 3) { self = self._value; } //也不會進入這里 if (Promise._onHandle) { Promise._onHandle(self); } //進入這里,注意這里,如果通過then的鏈式調用,那么每次then返回的對象都是一個新的類似于下面 p 實例對象; if (self._state === 0) { if (self._deferredState === 0) { self._deferredState = 1; self._deferreds = deferred; return; //第一次執行到這里即結束; } if (self._deferredState === 1) { self._deferredState = 2; self._deferreds = [self._deferreds, deferred]; return; } self._deferreds.push(deferred); return; } //這個函數只有當 _state的值為 1 2的時候才會執行 handleResolved(self, deferred); }
此時再來看下p這個promise實例的屬性值
p =>{ _deferredState:1,//deffer的狀態 _state:0,//每個promise對象的狀態維護標識 _value:null,//resolve函數執行的時候,異步得到的結果 _deferreds: new Handler(onFulfilled, onRejected, res)//存放通過then注冊的函數以及返回的??Promise實例對象的一個Handler對象; } res:{ _deferredState:0,//deffereds的狀態, _state:0,//每個promise對象的狀態維護標識 _value:null,//resolve函數執行的時候,異步得到的結果 _deferreds:null }
如果返回的res在執行then方法,那么
p =>{ _deferredState:1,//deffer的狀態 _state:0,//每個promise對象的狀態維護標識 _value:null,//resolve函數執行的時候,異步得到的結果 _deferreds: new Handler(onFulfilled, onRejected, res)//存放通過then注冊的函數以及返回的??Promise實例對象的一個Handler對象; } res:{ _deferredState:1,//deffereds的狀態, _state:0,//每個promise對象的狀態維護標識 _value:null,//resolve函數執行的時候,異步得到的結果 _deferreds:new Handler(onFulfilled, onRejected, res)//存放通過then注冊的函數以及返回的??Promise實例對象的一個Handler對象; }2.3 異步操作完成以后:resolve("someData");
//真正調用這個函數的是tryCallTwo中的第二個函數入參;self就是p這個promise實例對象; function resolve(self, newValue) { // 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 ( //比如resolve(p1) p1是一個新的promise對象; newValue && (typeof newValue === "object" || typeof newValue === "function") ) { var then = getThen(newValue); if (then === IS_ERROR) { return reject(self, LAST_ERROR); } if ( then === self.then && newValue instanceof Promise ) { self._state = 3; self._value = newValue; finale(self); return; } else if (typeof then === "function") { doResolve(then.bind(newValue), self); return; } } //對于簡單的返回值,比如后臺返回的JSON字符串等,這里就直接進行處理; self._state = 1;//fulfilled self._value = newValue;//給這個promise對象添加屬性值 _value,用來保存異步操作的結果; finale(self);//最后處理這個promise對象 }
此時的promise實例對象,關注對比p這個實例對象的變化,可以看到resolve之后,相當于將異步的結果給到了p這個Promise實例對象的_value屬性值,同時改變這個p的狀態_state為1 ==> fulfilled
p =>{ _deferredState:1,//deffer的狀態 _state:1,//每個promise對象的狀態維護標識 _value:"someData",//resolve函數執行的時候,異步得到的結果 _deferreds: new Handler(onFulfilled, onRejected, res) }2.4 finale(self);//最后處理這個promise對象
function finale(self) { //進入這個if語句 if (self._deferredState === 1) { handle(self, self._deferreds); self._deferreds = null; } if (self._deferredState === 2) { for (var i = 0; i < self._deferreds.length; i++) { handle(self, self._deferreds[i]); } self._deferreds = null; } }
function handle(self, deferred) { while (self._state === 3) { self = self._value; } if (Promise._onHandle) { Promise._onHandle(self); } //此時不會進入這里因為 _state的值為 1 if (self._state === 0) { if (self._deferredState === 0) { self._deferredState = 1; self._deferreds = deferred; return; } if (self._deferredState === 1) { self._deferredState = 2; self._deferreds = [self._deferreds, deferred]; return; } self._deferreds.push(deferred); return; } //這個函數只有當 _state的值為 1 fulfilled. 2 rejected 的時候才會執行 handleResolved(self, deferred); }
function handleResolved(self, deferred) { asap(function() { //得到promise.then(function(data){ console.log(data);});注冊的函數 var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; if (cb === null) { if (self._state === 1) { resolve(deferred.promise, self._value); } else { reject(deferred.promise, self._value); } return; } //執行then中注冊回調函數 var ret = tryCallOne(cb, self._value); if (ret === IS_ERROR) { reject(deferred.promise, LAST_ERROR); } else { resolve(deferred.promise, ret); } }); }; function tryCallOne(fn, a) { try { return fn(a); } catch (ex) { LAST_ERROR = ex; return IS_ERROR; } }
至此一個簡單的promsie的實現流程完畢;
下面用實際的例子來看下:
3 對于then的鏈式調用,Promise內部又是如何運行的呢? 下一個then中注冊的函數會接收到上一個then的返回值作為該then中注冊的函數的參數; 3.1 then注冊的函數返回基本數據類型function runAsync(){ let p = new Promise(function(resolve,reject){ console.log("exec"); setTimeout(function(){ resolve("someData"); },2000); }); return p; } var promise = runAsync(); promise.then(function(data){ console.log(data); return "someData1" }).then(function(data){ console.log(data); return "someData2" }).then(function(data){ console.log(data) }) console.log("同步執行"); console.log(promise);
控制臺輸出
exec 同步執行 Promise //兩秒后 someData someData1 someData2
resolve(deferred.promise, ret);中的ret值就是then中注冊函數的返回值,這里就是一些簡單的字符串"someData1" "someData2"
promise實例對象==> 異步成功 ==> 該實例對象的resolve(data) ==> //newValue為異步得到的數據,第一次是"someData"這個字符串,下一次就是then中注冊函數的返回值ret,還是字符串"someData1" "someData2" resolve(self,newValue) ==> <== == == == == == == || ^ ==>handle(self,deffer) || ^ ==>handleResolved處理then中注冊的函數; || ^ ==>接著處理下一個promis==>resolve(deferred.promise, ret); ===> ||
var p = { _deferredState:1,//deffer的狀態 _state:0,//每個promise對象的狀態維護標識 _value:null,//resolve函數執行的時候,異步得到的結果 _deferreds:{ onFulfilled:onFulfilled, onRejected:onRejected, promise:{//這里是 new Promise(noop) _deferredState:1, _state:0, _value:null, _deferreds:{//通過then注冊的執行對象 onFulfilled:onFulfilled, onRejected:onRejected, promise:{//這里是 new Promise(noop) _deferredState:1, _state:0, _value:null, _deferreds:{//通過then注冊的執行對象 onFulfilled:onFulfilled, onRejected:onRejected, promise:{//這里是 new Promise(noop) _deferredState:1 _state:0, _value:null, _deferreds:null }, } } } } } };3.2 then注冊的函數返回一個新的promise
function runAsync(){ let p = new Promise(function(resolve,reject){ console.log("exec"); setTimeout(function(){ resolve("someData"); },2000); }); return p; }; function runAsync1(){ return new Promise(function(resolve,reject){ setTimeout(function(){ resolve("someData1"); },2000); }) }; function runAsync2(){ return new Promise(function(resolve,reject){ setTimeout(function(){ resolve("someData2"); },2000); }) }; //以下的異步操作會按照順序進行執行; var promise = runAsync(); promise.then(function(data){ console.log(data); return runAsync1() }).then(function(data){ console.log(data); return runAsync2() }).then(function(data){ console.log(data); // return "someData3" }) console.log("同步執行"); console.log(promise);
控制臺輸出
exec 同步執行 Promise //兩秒后 someData //兩秒后 someData1 //兩秒后 someData2
promise實例對象 ==> 異步成功 ==> 該實例對象的resolve(data) ==> //newValue為異步得到的數據,這里第一次是 "someData"這個字符串,下一次就是then中注冊函數的返回值,這里就是runAsync返回的promise對象 resolve(self,newValue) ==> <== == == == == == == || ^ ==>handle(self,deffer) || ^ ==>handleResolved處理then中注冊的函數; || ^ ==>接著處理下一個promise==>resolve(deferred.promise, ret); ===> ||
整個promise鏈如下
var p = { _deferredState:1,//deffer的狀態 _state:0,//每個promise對象的狀態維護標識 _value:null,//resolve函數執行的時候,異步得到的結果 _deferreds:{ onFulfilled:onFulfilled, onRejected:onRejected, promise:{ //通過引用的地址改變,這里是runAsync返回的promise _deferredState:1, _state:0, _value:null, _deferreds:{//由于runAsync中沒有執行then注冊,這里將new Promise(noop) 通過then注冊的對象引用拿到; onFulfilled:onFulfilled, onRejected:onRejected, promise:{//通過引用的地址改變,這里是runAsync返回的promise _deferredState:1, _state:0, _value:null, _deferreds:{ onFulfilled:onFulfilled, onRejected:onRejected, promise:{//通過引用的地址改變,這里是runAsync返回的promise _deferredState:1, _state:0, _value:null, _deferreds:null }, } } } } } }3.3 以上兩者有何差異?
相同點:每個then返回的新的promise對象是一樣的,都是通過then函數中的定義的返回值:var res = new Promise(noop);
不同點:在handleResolved中,resolve(deferred.promise, ret);中的ret的值不同,ret就是每個then中注冊的函數的返回值,對比以上兩種情況,一個返回基本數據類型,一個返回Promise對象,接下來重點看下then中注冊的函數返回promise對象的情況(注意這個和then鏈式調用的promise對象不是一個)
// resolve(deferred.promise, ret);注意這個self,傳入的是deferred這個對象中promise這個引用地址; //真正調用這個函數的是tryCallTwo中的第二個函數入參;self就是p這個promise實例對象; function resolve(self, newValue) { //此時的newValue是then中注冊函數的返回的Promise實例對象 //self是deferred.promise // 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.") ); } //注意,對于then中注冊的函數返回值是一個新的promise對象的時候,此時會進入這里 if ( //比如resolve(p1) p1是一個新的promise對象; newValue && (typeof newValue === "object" || typeof newValue === "function") ) { var then = getThen(newValue); if (then === IS_ERROR) { return reject(self, LAST_ERROR); } if ( //兩個Promise對象原型鏈上都是引用的then這個函數地址 then === self.then && newValue instanceof Promise ) { self._state = 3; self._value = newValue; finale(self); //執行到這里,結束; return; } else if (typeof then === "function") { doResolve(then.bind(newValue), self); return; } } //對于then中注冊的函數返回一個promise對象的情況,下面就不會執行 self._state = 1; self._value = newValue; finale(self); }
self ==> deferred.promise
function finale(self) { if (self._deferredState === 1) { handle(self, self._deferreds); self._deferreds = null; } if (self._deferredState === 2) { for (var i = 0; i < self._deferreds.length; i++) { handle(self, self._deferreds[i]); } self._deferreds = null; } }
注意在這里通過對promise鏈進行引用的改變,從而使異步的執行看起來和同步是一樣的;
handle函數有兩個作用,
第一:改變promise鏈的引用,將原本返回的 new Promsie(noop) 改為ret(then中注冊函數返回的promise)
第二:將原本new Promsie(noop) 上面通過then注冊deferred對象,給到ret響應的屬性
function handle(self, deferred) { while (self._state === 3) { //這里一直循環直到取到我們返回的promsie對象,也就是上面的ret,即每個runAsync函數的返回值; self = self._value; } if (Promise._onHandle) { Promise._onHandle(self); } //將runAsync的返回的promise對象中_deferredState設置為 1; if (self._state === 0) { if (self._deferredState === 0) { self._deferredState = 1; self._deferreds = deferred; //執行到這里結束 return; } if (self._deferredState === 1) { self._deferredState = 2; self._deferreds = [self._deferreds, deferred]; return; } self._deferreds.push(deferred); return; } handleResolved(self, deferred); }4 綜合練習
對于注釋的代碼可以來回切換,看下結果。
function runAsync(){ let p = new Promise(function(resolve,reject){ console.log("exec"); setTimeout(function(){ resolve("someData"); },2000); }); return p; }; function runAsync1(){ return new Promise(function(resolve,reject){ setTimeout(function(){ console.log("異步1") // resolve("someData1"); reject("error1") },2000); }) }; function runAsync2(){ return new Promise(function(resolve,reject){ setTimeout(function(){ console.log("異步2") // resolve("someData2"); reject("error2") },2000); }) } var promise = runAsync(); promise.then(function(data){ console.log(data); return runAsync1() }).then(function(data){ console.log(data); return runAsync2() }).then(function(data){ console.log(data); // return "someData3" }).catch(function(error){ console.log(error) }) console.log("同步執行"); console.log(promise);
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/92272.html
摘要:雙向數據綁定的核心和基礎是其內部真正參與數據雙向綁定流程的主要有和基于和發布者訂閱者模式,最終實現數據的雙向綁定。在這里把雙向數據綁定分為兩個流程收集依賴流程依賴收集會經過以上流程,最終數組中存放列表,數組中存放列表。 Vue雙向數據綁定的核心和基礎api是Object.defineProperty,其內部真正參與數據雙向綁定流程的主要有Obderver、Dep和Watcher,基于d...
摘要:大家可以看到是構造函數構造出來的,并且內部有一個對象,這個對象是本文接下來要重點介紹的對象,接下來我們就來一窺究竟吧。在構造函數內部就進行了一步操作,那就是創建了一個對象,并掛載到了上。下一篇文章還是流程相關的內容。這是我的剖析 React 源碼的第二篇文章,如果你沒有閱讀過之前的文章,請務必先閱讀一下 第一篇文章 中提到的一些注意事項,能幫助你更好地閱讀源碼。 文章相關資料 React ...
摘要:就是,如果你不了解這個的話可以閱讀下相關文檔,是應用初始化時就會生成的一個變量,值也是,并且這個值不會在后期再被改變。這是我的剖析 React 源碼的第三篇文章,如果你沒有閱讀過之前的文章,請務必先閱讀一下 第一篇文章 中提到的一些注意事項,能幫助你更好地閱讀源碼。 文章相關資料 React 16.8.6 源碼中文注釋,這個鏈接是文章的核心,文中的具體代碼及代碼行數都是依托于這個倉庫 熱身...
閱讀 928·2021-11-24 09:38
閱讀 944·2021-11-23 09:51
閱讀 2951·2021-11-16 11:44
閱讀 1782·2021-09-22 15:52
閱讀 1686·2021-09-10 11:20
閱讀 1411·2019-08-30 13:47
閱讀 1305·2019-08-29 12:36
閱讀 3340·2019-08-26 10:43