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

資訊專(zhuān)欄INFORMATION COLUMN

從狀態(tài)機(jī)的角度加深理解并實(shí)現(xiàn)Promise

IamDLY / 928人閱讀

摘要:這篇文章內(nèi)容主要來(lái)自一篇高票答案聲明此的實(shí)現(xiàn)僅僅是為了加深本人對(duì)其的理解,和規(guī)范有些出入,但是的確是目前看過(guò)所有代碼中最漂亮,思路比較清晰的一個(gè)。

這篇文章內(nèi)容主要來(lái)自一篇stack Overflow高票答案

聲明:此Promise的實(shí)現(xiàn)僅僅是為了加深本人對(duì)其的理解,和A+規(guī)范有些出入,但是的確是目前看過(guò)所有promise代碼中最漂亮,思路比較清晰的一個(gè)。
文章不會(huì)特意幫助讀者復(fù)習(xí)Promise基本操作。

狀態(tài)機(jī)

Promise其實(shí)本質(zhì)上就是一個(gè)狀態(tài)機(jī),所以首先我們描述一個(gè)靜態(tài)的狀態(tài)機(jī),就像下邊這樣

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise() {
  // 存儲(chǔ)的狀態(tài)是上邊的三個(gè):執(zhí)行中,已完成,已拒絕
  var state = PENDING;

  // 存儲(chǔ)異步結(jié)果或者異步錯(cuò)誤消息
  var value = null;

  // 負(fù)責(zé)處理中途加入的處理函數(shù)
  var handlers = [];
}
狀態(tài)改變

完成了基本的狀態(tài)機(jī)定義,接下來(lái)的問(wèn)題就是完成“狀態(tài)改變”這個(gè)動(dòng)作的實(shí)現(xiàn):

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise() {
  // 存儲(chǔ)三個(gè)狀態(tài)
  var state = PENDING;

  // 一旦出現(xiàn)狀態(tài)的改變,異步結(jié)果就會(huì)被存到這個(gè)地方
  var value = null;

  // 存儲(chǔ)成功或者失敗的handler
  var handlers = [];

//狀態(tài)轉(zhuǎn)移到成功
  function fulfill(result) {
    state = FULFILLED;
    value = result;
  }
//狀態(tài)轉(zhuǎn)移到失敗
  function reject(error) {
    state = REJECTED;
    value = error;
  }
}

到目前為止,我們給出了兩個(gè)很純粹的變化動(dòng)作,在開(kāi)發(fā)的過(guò)程中這兩個(gè)動(dòng)作會(huì)很不好用,所以我們?cè)谶@兩個(gè)動(dòng)作的基礎(chǔ)上構(gòu)建一個(gè)高層次的動(dòng)作(其實(shí)就是加點(diǎn)判斷然后封裝一層),就像下邊這兒,名字就叫做resolve,但是注意和我們正常使用promise調(diào)用的那個(gè)resolve并不一樣,不要搞混:

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise() {

  var state = PENDING;
  var value = null;
  var handlers = [];

  function fulfill(result) {
    state = FULFILLED;
    value = result;
  }

  function reject(error) {
    state = REJECTED;
    value = error;
  }
//這里暫時(shí)缺少兩個(gè)重要函數(shù)getThen和doResolve這兩個(gè)函數(shù),稍后會(huì)說(shuō)道
  function resolve(result) {
    try {
      var then = getThen(result);
      //判斷then是不是一個(gè)Promise對(duì)象
      if (then) {
        doResolve(then.bind(result), resolve, reject)
        return
      }
      fulfill(result);
    } catch (e) {
      reject(e);
    }
  }
}

是的,我們的用到了兩個(gè)輔助函數(shù)getThen和doResolve,現(xiàn)在給出實(shí)現(xiàn):

/**
 * 這里會(huì)判斷value的類(lèi)型,我們只要promise.then這個(gè)函數(shù),其他的統(tǒng)統(tǒng)返回null
 *
 * @param {Promise|Any} value
 * @return {Function|Null}
 */
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;
}

/**
 * 這個(gè)函數(shù)的主要作用就是串主邏輯,完成“變化狀態(tài)”這個(gè)動(dòng)作
 *
 * @param {Function} fn A resolver function that may not be trusted
 * @param {Function} onFulfilled
 * @param {Function} onRejected
 */
function doResolve(fn, onFulfilled, onRejected) {
//done的作用是讓onFulfilled或者onRejected僅僅被調(diào)用一次,狀態(tài)機(jī)狀態(tài)一旦改變沒(méi)法回頭
  var done = false;
  try {
//在我們正常使用Promise的時(shí)候調(diào)的resolve,其實(shí)用的就是這里fn注入函數(shù)然后調(diào)用
    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)
  }
}
構(gòu)建

好了,一個(gè)完整的狀態(tài)機(jī)已經(jīng)完成,我們完成了一個(gè)基本的狀態(tài)變化邏輯,接下來(lái)要做的就是一步一步的朝promise標(biāo)準(zhǔn)進(jìn)發(fā),這個(gè)promise缺少什么呢,暫時(shí)缺的就是初始的動(dòng)作啦(new promise(func)對(duì)象一旦被初始化內(nèi)部代碼立即執(zhí)行),所以我們加上初始動(dòng)作的開(kāi)啟

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise(fn) {

  var state = PENDING;
  var value = null;
  var handlers = [];

  function fulfill(result) {
    state = FULFILLED;
    value = result;
  }

  function reject(error) {
    state = REJECTED;
    value = error;
  }

  function resolve(result) {
    try {
      var then = getThen(result);
      if (then) {
        doResolve(then.bind(result), resolve, reject)
        return
      }
      fulfill(result);
    } catch (e) {
      reject(e);
    }
  }
//開(kāi)啟任務(wù)的執(zhí)行,所以我說(shuō)doResolve其實(shí)才是“主線任務(wù)”的引子,而fn其實(shí)就是你寫(xiě)的代碼
  doResolve(fn, resolve, reject);
}
聯(lián)動(dòng)

我們實(shí)現(xiàn)了狀態(tài)機(jī),但是目前的問(wèn)題是我們只能眼睜睜的看著代碼的流動(dòng)直到一個(gè)Promise結(jié)束為止,即沒(méi)法添加也沒(méi)法獲取結(jié)果,這就有很大的局限性了,所以我們要使用then方法來(lái)串聯(lián)Promise,用done方法來(lái)完成結(jié)果的收集,首先實(shí)現(xiàn)done方法,因?yàn)閠hen其實(shí)說(shuō)白了就是收集上邊的結(jié)果--完成自己的邏輯--把結(jié)果傳遞給下一個(gè)Promise,做的事情是done的超集。

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise(fn) {

  var state = PENDING;
  var value = null;
  var handlers = [];

  function fulfill(result) {
    state = FULFILLED;
    value = result;
    //專(zhuān)門(mén)封裝一個(gè)handle函數(shù)處理后續(xù)邏輯,在下面有this.handle(handler)方法
    handlers.forEach(handle);
    //在狀態(tài)變成已處理并且之前加入的handler都被處理完畢的情況下再加入handler就會(huì)報(bào)錯(cuò)并且沒(méi)有卵用
    handlers = null;
  }

  function reject(error) {
    state = REJECTED;
    value = error;
    handlers.forEach(handle);
    handlers = null;
  }

  function resolve(result) {
    try {
      var then = getThen(result);
      if (then) {
        doResolve(then.bind(result), resolve, reject)
        return
      }
      fulfill(result);
    } catch (e) {
      reject(e);
    }
  }

  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);
      }
    }
  }

//注意看下面done方法的實(shí)現(xiàn),里邊只有一個(gè)異步方法,換句話說(shuō)就是會(huì)立即返回不會(huì)產(chǎn)生阻塞,我們之后會(huì)在then當(dāng)中調(diào)用done方法,這里的onFulfilled, onRejected就是用戶寫(xiě)的處理函數(shù),promise異步的特性就是這樣來(lái)的。
  this.done = function (onFulfilled, onRejected) {
    // ensure we are always asynchronous
    setTimeout(function () {
      handle({
        onFulfilled: onFulfilled,
        onRejected: onRejected
      });
    }, 0);
  }

  doResolve(fn, resolve, reject);
}

最后,我們來(lái)實(shí)現(xiàn)Promise.then,完成狀態(tài)機(jī)的串聯(lián):

//這段代碼有點(diǎn)繞,主要需要完成的工作其實(shí)就是,判斷上一個(gè)Promise是否完成,然后執(zhí)行用戶的then里邊的回調(diào)代碼,并最終返回一個(gè)新的Promise,然后依次循環(huán)。。。
this.then = function (onFulfilled, onRejected) {
//開(kāi)啟then之后就會(huì)返回一個(gè)新的promise,但是這個(gè)時(shí)候我們還可能有上一個(gè)Promise的任務(wù)沒(méi)有完成,所以先把上邊一個(gè)promise對(duì)象的this指向保存下來(lái)
  var self = this;
//返回一個(gè)新包裝Promise,這和我們普通的在外邊寫(xiě)new Promise是一個(gè)道理
  return new Promise(function (resolve, reject) {
//done的代碼同樣是立即返回,然后異步執(zhí)行的
    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);
      }
    });
  });
}

Over
更多參考請(qǐng)看下面:
簡(jiǎn)單的實(shí)現(xiàn)Promsie
高性能實(shí)現(xiàn)Promise,以及專(zhuān)門(mén)的wiki

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

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

相關(guān)文章

  • 源碼看 Promise 概念與實(shí)現(xiàn)

    摘要:從源碼看概念與實(shí)現(xiàn)是異步編程中的重要概念,它較好地解決了異步任務(wù)中回調(diào)嵌套的問(wèn)題。這些概念中有趣的地方在于,標(biāo)識(shí)狀態(tài)的變量如都是形容詞,用于傳入數(shù)據(jù)的接口如與都是動(dòng)詞,而用于傳入回調(diào)函數(shù)的接口如及則在語(yǔ)義上用于修飾動(dòng)詞的副詞。 從源碼看 Promise 概念與實(shí)現(xiàn) Promise 是 JS 異步編程中的重要概念,它較好地解決了異步任務(wù)中回調(diào)嵌套的問(wèn)題。在沒(méi)有引入新的語(yǔ)言機(jī)制的前提下,這...

    kel 評(píng)論0 收藏0
  • 深入理解promise對(duì)象

    摘要:前言中的異步,剛開(kāi)始的時(shí)候都是用回調(diào)函數(shù)實(shí)現(xiàn)的,所以如果異步嵌套的話,就有出現(xiàn)回調(diào)地獄,使得代碼難以閱讀和難以維護(hù),后來(lái)出現(xiàn)了,解決了回調(diào)地獄的問(wèn)題。 前言 js中的異步,剛開(kāi)始的時(shí)候都是用回調(diào)函數(shù)實(shí)現(xiàn)的,所以如果異步嵌套的話,就有出現(xiàn)回調(diào)地獄,使得代碼難以閱讀和難以維護(hù),后來(lái)es6出現(xiàn)了promise,解決了回調(diào)地獄的問(wèn)題?,F(xiàn)在我們就自己寫(xiě)代碼實(shí)現(xiàn)一下promise,這樣才能深入理解...

    CoderDock 評(píng)論0 收藏0
  • spring statemachine的企業(yè)可用級(jí)開(kāi)發(fā)指南1-說(shuō)些廢話

    摘要:讓我們先看下?tīng)顟B(tài)機(jī)的概念。下面是狀態(tài)機(jī)模型中的個(gè)要素,即現(xiàn)態(tài)條件動(dòng)作次態(tài)。因?yàn)橛唵魏蛯徟亩加泻芏嗟牧鞒蹋總€(gè)流程都會(huì)產(chǎn)生狀態(tài)的變化,而且流程是這種業(yè)務(wù)的主軸,其他都是圍繞這個(gè)流程和狀態(tài)變化來(lái)考慮的,所以看起來(lái)蠻適合用狀態(tài)機(jī)來(lái)做。 1、背景在我打算學(xué)習(xí)spring statemachine的時(shí)候,我?guī)缀蹩催^(guò)了所有網(wǎng)上的中文教程,基本上都處于淺嘗輒止的階段,有幾篇講的比較深入的,都只是...

    BakerJ 評(píng)論0 收藏0
  • 白潔血戰(zhàn)Node.js發(fā)編程 01 狀態(tài)機(jī)

    摘要:狀態(tài)機(jī)狀態(tài)機(jī)是模型層面的概念,與編程語(yǔ)言無(wú)關(guān)。狀態(tài)機(jī)具有良好的可實(shí)現(xiàn)性和可測(cè)試性。在代碼里,這是一個(gè),但是我們?cè)跔顟B(tài)機(jī)模型中要把他理解為事件。 這一篇是這個(gè)系列的開(kāi)篇,沒(méi)有任何高級(jí)內(nèi)容,就講講狀態(tài)機(jī)。 狀態(tài)機(jī) 狀態(tài)機(jī)是模型層面的概念,與編程語(yǔ)言無(wú)關(guān)。它的目的是為對(duì)象行為建模,屬于設(shè)計(jì)范疇。它的基礎(chǔ)概念是狀態(tài)(state)和事件(event)。 對(duì)象的內(nèi)部結(jié)構(gòu)描述為一組狀態(tài)S1, S2,...

    fjcgreat 評(píng)論0 收藏0
  • 簡(jiǎn)單理解Javascript的各種異步流程控制方法

    摘要:所以僅用于簡(jiǎn)化理解,快速入門(mén),依然需要閱讀有深入研究的文章來(lái)加深對(duì)各種異步流程控制的方法的掌握。 原文地址:http://zodiacg.net/2015/08/javascript-async-control-flow/ 隨著ES6標(biāo)準(zhǔn)逐漸成熟,利用Promise和Generator解決回調(diào)地獄問(wèn)題的話題一直很熱門(mén)。但是對(duì)解決流程控制/回調(diào)地獄問(wèn)題的各種工具認(rèn)識(shí)仍然比較麻煩。最近兩天...

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

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

0條評(píng)論

閱讀需要支付1元查看
<