摘要:調用初始的的方法,將匿名函數和匿名函數添加到原始的回調列表。當的狀態發生了改變,相關的回調函數會被執行,上面注冊的是的和方法作為的回調函數,那么的函數會在的狀態改變后被執行,那么的狀態就發生了改變。
Promise實現代碼分析
全是去嘗試理解別人是怎么實現promise的,感覺下面這兩個鏈接的Promise實現比較好。
實現1 實現2
實現2的配圖以及講解更細致一點,如果能跟著作者舉的例子走一遍,應該能夠理解為什么可以then().then().then(),以及理解為啥resolve(Promise)的狀態為啥是由參數的promise的狀態來決定的,也能理解resolve(value)的參數是如何傳遞給后續的通過then注冊的function的。但是30分鐘有點少,猶猶豫豫,糾結得看了好久。
相對而言,實現1的較為完整,實現2的某些東西只是提到了,但是沒提供實現。比如resolve/reject都只能調用一次。
實現1
function doResolve(fn, onFulfilled, onRejected) { var done = false; try { fn(function (value) { if (done) return done = true onFulfilled(value) }, function (reason) { if (done) return done = true onRejected(reason) }) } catch (ex) { if (done) return done = true onRejected(ex) } }
var promise = new Promise(fn);
fn是創建promise傳入的參數,它是一個function,在創建Promise的過程中需要被調用。
這個fn有兩個參數,都是function,前面一個是在fn按照得到了正常的結果之后調用的,那么then注冊的onfulfilled的方法就會在完成之后調用。另外一個就是fn遇到了意料之外的結果,相應的就會調用then注冊的onrejected方法。
doResolve的方法就是讓fn只能調用一次resolve或者一次reject方法,即只能改變promise的狀態一次。
this.done = function (onFulfilled, onRejected) { // ensure we are always asynchronous setTimeout(function () { handle({ onFulfilled: onFulfilled, onRejected: onRejected }); }, 0); }
這個done方法主要是把注冊的方法加入到自己這個Promise的回調列表里面。同時為了保證通過then方法注冊的function,都要在resolve之后才能調用,用了setTimeout來保證這一點(實現2是這么說的,雖然是在不同的地方用setTimeout)。
function handle(handler) { if (state === PENDING) { handlers.push(handler); } else { if (state === FULFILLED && typeof handler.onFulfilled === "function") { handler.onFulfilled(value); } if (state === REJECTED && typeof handler.onRejected === "function") { handler.onRejected(value); } } }
handle這個方法,比實現2的方法要簡單一點,因為相關的邏輯在then方法里面體現了。
這個其實就是通過當前的狀態來判斷是把回調加到回調列表里面還是直接執行fulfill或者reject方法。
this.then = function (onFulfilled, onRejected) { var self = this; return new Promise(function (resolve, reject) { return self.done(function (result) { if (typeof onFulfilled === "function") { try { return resolve(onFulfilled(result)); } catch (ex) { return reject(ex); } } else { return resolve(result); } }, function (error) { if (typeof onRejected === "function") { try { return resolve(onRejected(error)); } catch (ex) { return reject(ex); } } else { return reject(error); } }); }); }
then方法很關鍵,也較難懂。這邊寫的有點多,感覺實現2寫的好一點,把這些邏輯放在另外一個位置而不是在構建新promise的過程中。單純從理解上來講。
首先分析下每個參數的意思。
this.then = function (onFulfilled, onRejected)這里面的onFulfilled,onRejected是then方法給當前這個Promise注冊的兩個方法。
return new Promise(function (resolve, reject)這里的return new Promise就是為了新建一個Promise從而可以進行鏈式then方法的調用. then(fn1,fn2).then(fn3,fn4)=>var promise = then(fn1,fn2);
promise.then(fn3,fn4);resolve和reject則是這個新生成的promise的狀態設置方法。
self.done(function (result),function(error));調用初始的promise的done方法,將匿名函數function(result)和匿名函數function(error)添加到原始promise的回調列表。
然后再來看看匿名函數function(result)應該怎么執行。
function (result) { if (typeof onFulfilled === "function") { try { return resolve(onFulfilled(result)); } catch (ex) { return reject(ex); } } else { return resolve(result); } }
如果then方法注冊的是function,那么肯定是要用這個function去執行,onFulfilled(result)就是這個作用。
resolve是新產生的resolve的狀態設定器。執行完onFulfilled(result),產生的結果假如是newresult再交給resolve去執行。新的promise的resolve方法就會將新的promise的狀態設置成fulfilled,那么新promise的then方法就可以在注冊完后續的方法后接著執行。resolve(newresult)就將onFulfilled(result)產生的結果
傳遞給了后續的then方法注冊的function。
function getThen(value) { var t = typeof value; if (value && (t === "object" || t === "function")) { var then = value.then; if (typeof then === "function") { return then; } } return null; }
getThen方法是為了查看這個結果是不是一個Promise或者說是含有then方法的Object.如果有then方法,就把then方法返回,否則就返回null
function resolve(result) { try { var then = getThen(result); if (then) { doResolve(then.bind(result), resolve, reject) return } fulfill(result); } catch (e) { reject(e); } }
resolve這個方法可以處理參數是正常數值或者是Promise。根據Promise的使用說明,A promise resolve(Promise B),那么Promise A的狀態會在Promise B的狀態發生變化(變成fulfilled或者rejected)才會變化。首先用getThen來確定給定的參數是不是有then函數的Object,如果不是,那么就是單純的將值賦給Promise A的內部變量value,后續回調函數就可以用這個value作為參數,這也是為什么resolve能把其參數傳給通過then注冊的回調函數。那么如果是有then函數的object呢,首先getThen返回了那個object的then函數。
然后then.bind(result)是讓then函數的調用在擁有這個then函數的object里面執行,也就是resolve的參數result。然后doResolve實際上也就是執行了result這個promise的then方法。只不過注冊的兩個方法是當前這個
promise的resolve和reject方法。
所以實際上執行的是promiseB.then(resolve,reject);根據我們前面對then方法的分析可以知道。當promiseB的狀態發生了改變,相關的回調函數會被執行,上面注冊的是Promise A的resolve和reject方法作為promiseB的回調函數,那么Promise A的resolve/reject函數會在promiseB的狀態改變后被執行,那么PromiseA的狀態就發生了改變。同時PromiseB中產生的結果也會通過resolve這個函數傳給Promise A.
這個其實看實現2的handle方法以及then如何調用handle方法會更容易理解一點。而且作者畫了個很詳細的圖。
還忘了一點,就是為啥then方法前面有this。后來我覺得無所謂,然后把this去掉了,結果在調用的時候沒法調用這個then函數。this.then應該是接口吧。雖然當時在W3Cschool上學習原型構造的時候很認真,但是還是忽略了習以為常的this。直到有的function有this,有的沒有,才感覺有點奇怪,我自己寫的時候怎么判斷要不要加this啊。
大致就是這樣。匿名函數的調用,傳入的參數以及實際使用的參數,會引起很多干擾,說到底還是不太熟悉javascript的調用和特色吧。但是應該有更好的書寫方式吧。所說的東西只是自以為是的理解,實在很難確信自己是對的。因為覺得是對的,所以就會朝那個方向去靠,有點像老師解答試卷的標準答案一樣,即使標準答案是錯的。網上還是充斥著很多不怎么準確的東西的,還是按照自己的意愿、想法去測試下。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90298.html
摘要:遺傳算法物競天擇,適者生存,遺傳算法就是借鑒生物體自然選擇和自然遺傳機制的隨機搜索算法。隨機生成的基因適應度的最大值隨機生成,適應度函數計算種群中所有對象的適應度及總和,并對超出的基因進行懲罰。 此為《算法的樂趣》讀書筆記,我用javascript(ES6)重新實現算法。 遺傳算法 物競天擇,適者生存,遺傳算法就是借鑒生物體自然選擇和自然遺傳機制的隨機搜索算法。算法的關鍵點有:基因的選...
摘要:強烈推薦上值得前端學習的數據結構與算法項目,包含圖的演示過程與視頻講解。該倉庫包含了多種基于的算法與數據結構,提供進一步閱讀的解釋和鏈接。數據結構和算法必知必會的個代碼實現。 showImg(https://segmentfault.com/img/bVbvpYZ); 前言 算法為王。想學好前端,先練好內功,內功不行,就算招式練的再花哨,終究成不了高手;只有內功深厚者,前端之路才會走得...
摘要:筆者寫的數據結構與算法之美系列用的語言是,旨在入門數據結構與算法和方便以后復習。這應該是目前較為簡單的十大經典排序算法的文章講解了吧。比如原本在的前面,而,排序之后,在的后面十大經典排序算法冒泡排序思想冒泡排序只會操作相鄰的兩個數據。 showImg(https://segmentfault.com/img/bVbvHet); 1. 前言 算法為王。想學好前端,先練好內功,內功不行,就...
摘要:回顧選擇排序,插入排序,冒泡排序,快速排序,希爾排序,歸并排序,堆排序以及如何計算時間復雜度學習文章同學的描述數據結構等同學的十大經典算法本文代碼也上傳到了排序算法回顧。但希爾排序是非穩定排序算法。 回顧選擇排序,插入排序,冒泡排序,快速排序,希爾排序,歸并排序,堆排序以及如何計算時間復雜度學習文章:hahda同學的javascript描述數據結構、hustcc等同學的十大經典算法 ...
摘要:之所以把計數排序桶排序基數排序放在一起比較,是因為它們的平均時間復雜度都為。動畫計數排序思想找出待排序的數組中最大和最小的元素。桶排序計數排序能派上用場嗎手機號碼有位,范圍太大,顯然不適合用這兩種排序算法。 showImg(https://segmentfault.com/img/bVbuF9e?w=900&h=500); 1. 前言 算法為王。 想學好前端,先練好內功,只有內功深厚者...
摘要:之所以把冒泡排序選擇排序插入排序放在一起比較,是因為它們的平均時間復雜度都為。其中,冒泡排序就是原地排序算法。所以冒泡排序是穩定的排序算法。選擇排序思路選擇排序算法的實現思路有點類似插入排序,也分已排序區間和未排序區間。 showImg(https://segmentfault.com/img/bVbuvnj?w=900&h=250); 1. 前言 算法為王。 想學好前端,先練好內功,...
閱讀 904·2021-09-29 09:35
閱讀 1253·2021-09-28 09:36
閱讀 1522·2021-09-24 10:38
閱讀 1066·2021-09-10 11:18
閱讀 631·2019-08-30 15:54
閱讀 2496·2019-08-30 13:22
閱讀 1964·2019-08-30 11:14
閱讀 697·2019-08-29 12:35