成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Promise源碼學(xué)習(xí)(2)

cfanr / 2559人閱讀

摘要:源碼學(xué)習(xí)本篇為上一篇源碼學(xué)習(xí)的補(bǔ)充,主要是來介紹和方法。那個(gè)率先改變的實(shí)例的返回值,就傳遞給的回調(diào)函數(shù)?;窘榻B可見阮一峰老師的書籍。的狀態(tài)由決定,分成兩種情況。只有的狀態(tài)都變成,的狀態(tài)才會(huì)變成,此時(shí)的返回值組成一個(gè)數(shù)組,傳遞給的回調(diào)函數(shù)。

Promise源碼學(xué)習(xí)(2)

本篇為上一篇源碼學(xué)習(xí)(1)的補(bǔ)充,主要是來介紹Promise.all()和Promise.race()方法。
閑話少敘,進(jìn)入正題

Promise.race()

首先來簡單介紹一下功能吧,詳細(xì)比如可見阮一峰老師的ES6書籍。
Promise.race方法是將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例。

const p = Promise.race([p1, p2, p3]);

上面代碼中,只要p1、p2、p3之中有一個(gè)實(shí)例率先改變狀態(tài),p的狀態(tài)就跟著改變。那個(gè)率先改變的 Promise 實(shí)例的返回值,就傳遞給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í)行每一個(gè)傳入的entry 但只有最快的一個(gè)能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對(duì)象并在then中注冊(cè)回調(diào),設(shè)Promise.race()返回的新Promise的對(duì)象為p的話,最快執(zhí)行完成的entry進(jìn)入then回調(diào),執(zhí)行resolve或reject,以此來改變新對(duì)象p的狀態(tài)。之后的entry完成在此執(zhí)行resolve或reject均無效,因?yàn)镻romise狀態(tài)一旦確定無法改變,詳見上篇關(guān)于fulfill()和reject()的注釋和分析。

Promise.all()

基本介紹可見阮一峰老師的ES6書籍。
Promise.all方法用于將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例。

const p = Promise.all([p1, p2, p3]);

p的狀態(tài)由p1、p2、p3決定,分成兩種情況。
(1)只有p1、p2、p3的狀態(tài)都變成fulfilled,p的狀態(tài)才會(huì)變成fulfilled,此時(shí)p1、p2、p3的返回值組成一個(gè)數(shù)組,傳遞給p的回調(diào)函數(shù)。
(2)只要p1、p2、p3之中有一個(gè)被rejected,p的狀態(tài)就變成rejected,此時(shí)第一個(gè)被reject的實(shí)例的返回值,會(huì)傳遞給p的回調(diào)函數(shù)。
源碼:

export default function all(entries) {
  return new Enumerator(this, entries).promise;//這里返回了一個(gè)新對(duì)象Promise
}

這里注意返回了一個(gè)新的Promise對(duì)象.
Enumerator源碼如下

export default class Enumerator {
  constructor (Constructor, input) {
    this._instanceConstructor = Constructor;
    //Promise.all([...])會(huì)返回一個(gè)新的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);//每個(gè)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但是一個(gè)thenable
        let promise = new c(noop);
        handleMaybeThenable(promise, entry, then);
        this._willSettleAt(promise, i);//暫時(shí)狀態(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列表有一個(gè)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;
    //暫時(shí)狀態(tài)不定,訂閱之
    subscribe(
      promise, undefined,
      value => enumerator._settledAt(FULFILLED, i, value),//回調(diào),設(shè)置promise狀態(tài)
      reason => enumerator._settledAt(REJECTED, i, reason)
    );
  }
};

代碼不是很多,在此就不逐個(gè)方法貼了。
首先看Constructor,細(xì)節(jié)不表,如果傳入了一個(gè)thenable數(shù)組會(huì)在_enumerate方法中通過_eachEntry挨個(gè)處理,細(xì)節(jié)見注釋。
總體思路就是對(duì)傳入列表的元素挨個(gè)處理,該resolve則resolve,同時(shí)通過_remaining 對(duì)未完成的entry進(jìn)行計(jì)數(shù)。
若entry是pending狀態(tài),則通過_willSettleAt來訂閱,有確定結(jié)果時(shí)進(jìn)行 _settledAt;
若entry已完成,直接_settledAt確定結(jié)果;
當(dāng)_remaining === 0;也就是列表所有entry均已有結(jié)果,設(shè)置Promise.all()返回的新Promise對(duì)象的狀態(tài)。
要注意,如果有一個(gè)entry被reject了,會(huì)直接設(shè)置 新Promise對(duì)象的狀態(tài)為rejected。

總結(jié)


該圖對(duì)Promise的流程總結(jié)。
總的來說,Promise通過鏈?zhǔn)秸Z法使得異步操作更加的直觀,避免了回調(diào)地獄的出現(xiàn)。使得代碼更加易讀可維護(hù)。
細(xì)節(jié)可見源碼上的注釋,全部代碼可見es6-promise學(xué)習(xí)筆記

閑話

明后兩天公司集體出游,沒有大多的時(shí)間來打磨,可是自己又定了一個(gè)每周一篇學(xué)習(xí)總結(jié)小文章的目標(biāo),所以擠些時(shí)間提前寫完這篇文章來完成目標(biāo)吧。繼續(xù)加油吧!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/94468.html

相關(guān)文章

  • Promise源碼學(xué)習(xí)(1)

    摘要:工作當(dāng)中經(jīng)常會(huì)用到,在此進(jìn)行深入學(xué)習(xí)異步編程解決方案是異步編程的一種解決方案,比傳統(tǒng)的解決方案回調(diào)函數(shù)和事件更合理和更強(qiáng)大。所有源碼注釋見學(xué)習(xí)筆記 工作當(dāng)中經(jīng)常會(huì)用到Promise,在此進(jìn)行深入學(xué)習(xí) 異步編程解決方案 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。它由社區(qū)最早提出和實(shí)現(xiàn),ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了...

    young.li 評(píng)論0 收藏0
  • Promise學(xué)習(xí)筆記(四):源碼core.js解析(下)

    摘要:源碼閱讀階段緊接上一篇這次我們開始我們最常用到的部分的源碼解析傳入?yún)?shù)為兩個(gè)函數(shù)和判斷調(diào)用者是否為對(duì)象跳轉(zhuǎn)到了一個(gè)叫做的函數(shù)里面新建一個(gè)對(duì)象傳入函數(shù)傳入給和一個(gè)新的對(duì)象返回新的對(duì)象在這里我們先看看在調(diào)用者不是對(duì)象時(shí)到底做了什么比想象的要簡單 源碼閱讀階段 緊接上一篇,這次我們開始Promise我們最常用到的then部分的源碼解析. then() //傳入?yún)?shù)為兩個(gè)函數(shù),onFulfil...

    VincentFF 評(píng)論0 收藏0
  • Promise學(xué)習(xí)筆記(三):源碼core.js解析(上)

    摘要:源碼閱讀階段先理解根本吧想快點(diǎn)理解的話可以直接跳到下個(gè)標(biāo)題這部分根據(jù)理解將持續(xù)修改空函數(shù)用于判斷傳入構(gòu)造器的函數(shù)是否為空函數(shù)如果為空函數(shù)構(gòu)造一個(gè)對(duì)象并初始化狀態(tài)為終值回調(diào)狀態(tài)和隊(duì)列記錄內(nèi)部最后的一次錯(cuò)誤空對(duì)象標(biāo)識(shí)表示發(fā)生了錯(cuò)誤暴露模塊接口為 源碼閱讀階段 先理解Promise根本吧,想快點(diǎn)理解的話可以直接跳到下個(gè)標(biāo)題.這部分根據(jù)理解將持續(xù)修改. Promise(fn) function...

    wuyangchun 評(píng)論0 收藏0
  • 從react-start到co源碼(三)

    摘要:第三篇腳手架依賴的核心庫的源碼解析。該篇是這個(gè)系列文章的第三篇主要是對(duì)的源碼進(jìn)行分析講解。的源碼十分簡單但實(shí)現(xiàn)的功能卻是十分的強(qiáng)大。源碼概括源碼主要包含了兩部分公共方法和私有方法。 react作為當(dāng)前十分流行的前端框架,相信很多前端er都有蠢蠢欲動(dòng)的學(xué)習(xí)它的想法。工欲善其事,必先利其器。這篇文章就簡單的給大家介紹一下如何我快速的搭建一個(gè)react前端開發(fā)環(huán)境。主要針對(duì)于react小白,...

    wind5o 評(píng)論0 收藏0
  • Promise學(xué)習(xí)筆記(二):規(guī)范

    摘要:下一篇大概就是源碼方面的學(xué)習(xí)筆記了龜速學(xué)習(xí)中這一次我是去看了下規(guī)范照例傳送門圖靈社區(qū)規(guī)范首先吧個(gè)人總結(jié)下該用的詞解決結(jié)婚拒絕婉拒終值值傳家寶拒因好人卡等等異常車禍理下概念我們的的就像是一場姻緣對(duì)吧解決呢就是結(jié)婚成功啦傳家寶也如愿的傳給下一代 下一篇大概就是源碼方面的學(xué)習(xí)筆記了...龜速學(xué)習(xí)中... 這一次我是去看了下Promises/A+規(guī)范照例傳送門:圖靈社區(qū)Promises/A+規(guī)...

    _Suqin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<