摘要:源碼學習本篇為上一篇源碼學習的補充,主要是來介紹和方法。那個率先改變的實例的返回值,就傳遞給的回調(diào)函數(shù)。基本介紹可見阮一峰老師的書籍。的狀態(tài)由決定,分成兩種情況。只有的狀態(tài)都變成,的狀態(tài)才會變成,此時的返回值組成一個數(shù)組,傳遞給的回調(diào)函數(shù)。
Promise源碼學習(2)
本篇為上一篇源碼學習(1)的補充,主要是來介紹Promise.all()和Promise.race()方法。
閑話少敘,進入正題
首先來簡單介紹一下功能吧,詳細比如可見阮一峰老師的ES6書籍。
Promise.race方法是將多個 Promise 實例,包裝成一個新的 Promise 實例。
const p = Promise.race([p1, p2, p3]);
上面代碼中,只要p1、p2、p3之中有一個實例率先改變狀態(tài),p的狀態(tài)就跟著改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調(diào)函數(shù)。
接下來貼源代碼
export default function race (entries) { /*jshint validthis:true */ let Constructor = this; if (!isArray(entries)) { return new Constructor((_resolve, reject) => reject(new TypeError("You must pass an array to race."))); } else { return new Constructor((resolve, reject) => {//new 執(zhí)行一次 let length = entries.length; for (let i = 0; i < length; i++) {//執(zhí)行每一個傳入的entry 但只有最快的一個能resolve或reject改變返回的promise的狀態(tài) Constructor.resolve(entries[i]).then(resolve, reject); } }); } } //isArray定義: if (Array.isArray) { _isArray = Array.isArray; } else { _isArray = x => Object.prototype.toString.call(x) === "[object Array]"; }
如果傳入的參數(shù)不是數(shù)據(jù)直接reject。
如果是數(shù)組,則依次resolve傳入的thenable對象并在then中注冊回調(diào),設(shè)Promise.race()返回的新Promise的對象為p的話,最快執(zhí)行完成的entry進入then回調(diào),執(zhí)行resolve或reject,以此來改變新對象p的狀態(tài)。之后的entry完成在此執(zhí)行resolve或reject均無效,因為Promise狀態(tài)一旦確定無法改變,詳見上篇關(guān)于fulfill()和reject()的注釋和分析。
基本介紹可見阮一峰老師的ES6書籍。
Promise.all方法用于將多個 Promise 實例,包裝成一個新的 Promise 實例。
const p = Promise.all([p1, p2, p3]);
p的狀態(tài)由p1、p2、p3決定,分成兩種情況。
(1)只有p1、p2、p3的狀態(tài)都變成fulfilled,p的狀態(tài)才會變成fulfilled,此時p1、p2、p3的返回值組成一個數(shù)組,傳遞給p的回調(diào)函數(shù)。
(2)只要p1、p2、p3之中有一個被rejected,p的狀態(tài)就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調(diào)函數(shù)。
源碼:
export default function all(entries) { return new Enumerator(this, entries).promise;//這里返回了一個新對象Promise }
這里注意返回了一個新的Promise對象.
Enumerator源碼如下
export default class Enumerator { constructor (Constructor, input) { this._instanceConstructor = Constructor; //Promise.all([...])會返回一個新的promise this.promise = new Constructor(noop); if (!this.promise[PROMISE_ID]) { makePromise(this.promise); } if (isArray(input)) { this.length = input.length; this._remaining = input.length;//未完成的promise總數(shù)量 this._result = new Array(this.length);//每個promise結(jié)果 if (this.length === 0) { fulfill(this.promise, this._result); } else { this.length = this.length || 0; this._enumerate(input);//處理輸入的數(shù)組 if (this._remaining === 0) {//都執(zhí)行完畢 fulfill(this.promise, this._result); } } } else { reject(this.promise, validationError());//傳入不是array, reject it } } _enumerate (input) { for (let i = 0; this._state === PENDING && i < input.length; i++) {//Enumerator _state?? TODO this._eachEntry(input[i], i); } } //處理所有的輸入 _eachEntry (entry, i) { let c = this._instanceConstructor;//Promise let {resolve} = c;//Promise.resolve if (resolve === originalResolve) { let then = getThen(entry);//獲取then方法 if (then === originalThen && entry._state !== PENDING) {//如果entry已完成或已拒絕 this._settledAt(entry._state, i, entry._result); } else if (typeof then !== "function") { this._remaining--;//不是thenable 直接完成該entry this._result[i] = entry; } else if (c === Promise) {//不是promise但是一個thenable let promise = new c(noop); handleMaybeThenable(promise, entry, then); this._willSettleAt(promise, i);//暫時狀態(tài)不確定,訂閱之 } else { this._willSettleAt(new c(resolve => resolve(entry)), i); } } else { this._willSettleAt(resolve(entry), i); } } _settledAt (state, i, value) { let {promise} = this; if (promise._state === PENDING) { this._remaining--;//該entry狀態(tài)已確定,待完成總數(shù)減一 if (state === REJECTED) { reject(promise, value);//如果傳入entry列表有一個rejected,立即設(shè)置promise結(jié)果rejected } else { this._result[i] = value; } } if (this._remaining === 0) {//全部處理完成fulfill fulfill(promise, this._result); } } _willSettleAt (promise, i) { let enumerator = this; //暫時狀態(tài)不定,訂閱之 subscribe( promise, undefined, value => enumerator._settledAt(FULFILLED, i, value),//回調(diào),設(shè)置promise狀態(tài) reason => enumerator._settledAt(REJECTED, i, reason) ); } };
代碼不是很多,在此就不逐個方法貼了。
首先看Constructor,細節(jié)不表,如果傳入了一個thenable數(shù)組會在_enumerate方法中通過_eachEntry挨個處理,細節(jié)見注釋。
總體思路就是對傳入列表的元素挨個處理,該resolve則resolve,同時通過_remaining 對未完成的entry進行計數(shù)。
若entry是pending狀態(tài),則通過_willSettleAt來訂閱,有確定結(jié)果時進行 _settledAt;
若entry已完成,直接_settledAt確定結(jié)果;
當_remaining === 0;也就是列表所有entry均已有結(jié)果,設(shè)置Promise.all()返回的新Promise對象的狀態(tài)。
要注意,如果有一個entry被reject了,會直接設(shè)置 新Promise對象的狀態(tài)為rejected。
該圖對Promise的流程總結(jié)。
總的來說,Promise通過鏈式語法使得異步操作更加的直觀,避免了回調(diào)地獄的出現(xiàn)。使得代碼更加易讀可維護。
細節(jié)可見源碼上的注釋,全部代碼可見es6-promise學習筆記
明后兩天公司集體出游,沒有大多的時間來打磨,可是自己又定了一個每周一篇學習總結(jié)小文章的目標,所以擠些時間提前寫完這篇文章來完成目標吧。繼續(xù)加油吧!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/94468.html
摘要:工作當中經(jīng)常會用到,在此進行深入學習異步編程解決方案是異步編程的一種解決方案,比傳統(tǒng)的解決方案回調(diào)函數(shù)和事件更合理和更強大。所有源碼注釋見學習筆記 工作當中經(jīng)常會用到Promise,在此進行深入學習 異步編程解決方案 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強大。它由社區(qū)最早提出和實現(xiàn),ES6 將其寫進了語言標準,統(tǒng)一了用法,原生提供了...
摘要:源碼閱讀階段緊接上一篇這次我們開始我們最常用到的部分的源碼解析傳入?yún)?shù)為兩個函數(shù)和判斷調(diào)用者是否為對象跳轉(zhuǎn)到了一個叫做的函數(shù)里面新建一個對象傳入函數(shù)傳入給和一個新的對象返回新的對象在這里我們先看看在調(diào)用者不是對象時到底做了什么比想象的要簡單 源碼閱讀階段 緊接上一篇,這次我們開始Promise我們最常用到的then部分的源碼解析. then() //傳入?yún)?shù)為兩個函數(shù),onFulfil...
摘要:源碼閱讀階段先理解根本吧想快點理解的話可以直接跳到下個標題這部分根據(jù)理解將持續(xù)修改空函數(shù)用于判斷傳入構(gòu)造器的函數(shù)是否為空函數(shù)如果為空函數(shù)構(gòu)造一個對象并初始化狀態(tài)為終值回調(diào)狀態(tài)和隊列記錄內(nèi)部最后的一次錯誤空對象標識表示發(fā)生了錯誤暴露模塊接口為 源碼閱讀階段 先理解Promise根本吧,想快點理解的話可以直接跳到下個標題.這部分根據(jù)理解將持續(xù)修改. Promise(fn) function...
摘要:第三篇腳手架依賴的核心庫的源碼解析。該篇是這個系列文章的第三篇主要是對的源碼進行分析講解。的源碼十分簡單但實現(xiàn)的功能卻是十分的強大。源碼概括源碼主要包含了兩部分公共方法和私有方法。 react作為當前十分流行的前端框架,相信很多前端er都有蠢蠢欲動的學習它的想法。工欲善其事,必先利其器。這篇文章就簡單的給大家介紹一下如何我快速的搭建一個react前端開發(fā)環(huán)境。主要針對于react小白,...
摘要:下一篇大概就是源碼方面的學習筆記了龜速學習中這一次我是去看了下規(guī)范照例傳送門圖靈社區(qū)規(guī)范首先吧個人總結(jié)下該用的詞解決結(jié)婚拒絕婉拒終值值傳家寶拒因好人卡等等異常車禍理下概念我們的的就像是一場姻緣對吧解決呢就是結(jié)婚成功啦傳家寶也如愿的傳給下一代 下一篇大概就是源碼方面的學習筆記了...龜速學習中... 這一次我是去看了下Promises/A+規(guī)范照例傳送門:圖靈社區(qū)Promises/A+規(guī)...
閱讀 1993·2021-11-24 10:45
閱讀 1850·2021-10-09 09:43
閱讀 1291·2021-09-22 15:38
閱讀 1219·2021-08-18 10:19
閱讀 2837·2019-08-30 15:55
閱讀 3057·2019-08-30 12:45
閱讀 2962·2019-08-30 11:25
閱讀 356·2019-08-29 11:30