摘要:前言在異步編程之一中實現(xiàn)了一個異步函數(shù)調(diào)用鏈,它是一個順序調(diào)用鏈,很類似責(zé)任鏈模式,但現(xiàn)實往往不是平鋪直敘的,更多的其實是峰回路轉(zhuǎn),本文將繼續(xù)討論更多的用法。
前言
在《ES6 異步編程之一:Generator》中實現(xiàn)了一個異步函數(shù)調(diào)用鏈,它是一個順序調(diào)用鏈,很類似責(zé)任鏈模式,但現(xiàn)實往往不是平鋪直敘的,更多的其實是峰回路轉(zhuǎn),本文將繼續(xù)討論更多Generator的用法。
作為函數(shù)的Generator在之前的示例中,我們更多的是把生成器作為一個迭代器來循環(huán)調(diào)用每個函數(shù),但忽視了生成器也是個函數(shù),意味著生成器內(nèi)部可以實現(xiàn)復(fù)雜的業(yè)務(wù)邏輯,以下的代碼通過yield等待文件讀取結(jié)果并對結(jié)果進(jìn)行特定的處理,
function* generator() { let r1 = yield get("a"); if (r1) { let r2 = yield get("b"); if (r2) { console.log(yield get("d")); } } else { console.log(yield get("c")); } } let g = generator(); g.next();
如果get是個異步調(diào)用,以上的代碼想要能夠執(zhí)行則需要get函數(shù)執(zhí)行得到結(jié)果后調(diào)用生成器的next方法來推進(jìn),這要求get函數(shù)能持有生成器對象,這顯然并不容易。
偏函數(shù)偏函數(shù)(Partial Function)是對函數(shù)定義域的子集定義的函數(shù),形式上就是指定任意部分參數(shù)生成一個新的函數(shù),如下:
function sum(a, b, c) { return a + b + c; } function sum1(a) { return function(b, c) { return a + b + c; }; } function sum2(a, b) { return function(c) { return a + b + c; }; } sum(1, 2, 3) == sum1(1)(2, 3); //true sum(1, 2, 3) == sum2(1, 2)(3); //true
一般在設(shè)計異步調(diào)用api時,我們總是聲明一個參數(shù)來接收回調(diào)函數(shù),當(dāng)和偏函數(shù)相結(jié)合就變成這樣:
function get(f, callback) { delay(100, function(s) { callback(s + ":get " + f); }); } get("a", func); //調(diào)用get時必須立即傳入一個函數(shù) //轉(zhuǎn)換成偏函數(shù)形式: function partialGet(f) { return function(callback) { delay(100, function(s) { callback(s + ":get " + f); }); }; } let pGet = partialGet("a"); //可以先生成一個函數(shù) pGet(func); //需要時再傳入回調(diào)函數(shù)執(zhí)行
從上面的例子中可以發(fā)現(xiàn),偏函數(shù)能使定義和執(zhí)行分離,說來巧了,生成器可用于定義業(yè)務(wù)邏輯而生成器的next用于推進(jìn)業(yè)務(wù)執(zhí)行,二者也是相互分離的。
生成器和偏函數(shù)基于前面這么多鋪墊,假設(shè)get就是一個偏函數(shù),如下:
function get(f) { return function(callback) { delay(100, function(s) { callback(s + ":get " + f); }); }; }
這意味著,yield get("a")使得next函數(shù)執(zhí)行的結(jié)果其value屬性值是個函數(shù),該函數(shù)的參數(shù)是一個能接收get異步結(jié)果的回調(diào)函數(shù),即:
g.next().value(function(value) { g.next(value); //value成為yield的返回并繼續(xù)推進(jìn)業(yè)務(wù)邏輯 });
通過遞歸可以不斷的執(zhí)行生成器的next方法,一個全新的通過生成器來實現(xiàn)業(yè)務(wù)邏輯的run方法便呼之欲出了,
function run(gen) { let g = gen(); function next(lastValue) { let result = g.next(lastValue); //將上一個異步執(zhí)行結(jié)果傳出給當(dāng)前的yield并執(zhí)行下一個yield if (result.done) { return result.value; } //value是偏函數(shù)返回的新函數(shù),它的參數(shù)是個用來接收異步結(jié)果的回調(diào)函數(shù) result.value(next); //next作為接收異步結(jié)果的回調(diào)函數(shù) } next(); } run(generator);
綜合以上例子不難發(fā)現(xiàn)另外一個好處,通過偏函數(shù)可以使異步調(diào)用api不受生成器的侵入,《ES6 異步編程之一:Generator》中實現(xiàn)的異步調(diào)用需要將生成器作為參數(shù),有興趣的話你可以嘗試改造一下之前的示例。
現(xiàn)在通過新編寫的run函數(shù)就可以來執(zhí)行本文一開始編寫的那個生成器了。
thunkify偏函數(shù)的方案對api和生成器也是有侵入的,他要求:
api必須是偏函數(shù)形式;
生成器定義業(yè)務(wù)邏輯,每個yield 后面的函數(shù)必須是調(diào)用偏函數(shù);
第二個問題是本方案的核心機(jī)制所要求,但第一個問題我們可以通過thunkify來解決,api依舊按照get(value, callback)方式定義,但定義生成器時需要將異步api調(diào)用通過thunkify轉(zhuǎn)換為偏函數(shù),如下:
let Thunkify = require("thunkify"); let thunkifiedGet = Thunkify(get); function get(f, callback) { delay(100, function(s) { callback(s + ":get " + f); }); } function* generator() { let r1 = yield thunkifiedGet("a"); if (r1) { let r2 = yield thunkifiedGet("b"); if (r2) { console.log(yield thunkifiedGet("d")); } } else { console.log(yield thunkifiedGet("c")); } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/81484.html
摘要:回調(diào)函數(shù)這是異步編程最基本的方法。對象對象是工作組提出的一種規(guī)范,目的是為異步編程提供統(tǒng)一接口。誕生后,出現(xiàn)了函數(shù),它將異步編程帶入了一個全新的階段。 更多詳情點(diǎn)擊http://blog.zhangbing.club/Ja... Javascript 語言的執(zhí)行環(huán)境是單線程的,如果沒有異步編程,根本沒法用,非卡死不可。 為了解決這個問題,Javascript語言將任務(wù)的執(zhí)行模式分成兩種...
摘要:傳統(tǒng)的異步方法回調(diào)函數(shù)事件監(jiān)聽發(fā)布訂閱之前寫過一篇關(guān)于的文章,里邊寫過關(guān)于異步的一些概念。內(nèi)部函數(shù)就是的回調(diào)函數(shù),函數(shù)首先把函數(shù)的指針指向函數(shù)的下一步方法,如果沒有,就把函數(shù)傳給函數(shù)屬性,否則直接退出。 Generator函數(shù)與異步編程 因為js是單線程語言,所以需要異步編程的存在,要不效率太低會卡死。 傳統(tǒng)的異步方法 回調(diào)函數(shù) 事件監(jiān)聽 發(fā)布/訂閱 Promise 之前寫過一篇關(guān)...
摘要:環(huán)境中產(chǎn)生異步操作的函數(shù)分為兩大類計時函數(shù)和函數(shù)。如果要在應(yīng)用中定義復(fù)雜的異步操作,就要使用者兩類異步函數(shù)作為基本的構(gòu)造快。在本例子中同步事件循環(huán)不包含內(nèi)部的外部的異步事件循環(huán)內(nèi)部的。其弊端是操作強(qiáng)耦合維護(hù)代價高。 JavaScript環(huán)境中產(chǎn)生異步操作的函數(shù)分為兩大類:計時函數(shù)和I/O函數(shù)。如果要在應(yīng)用中定義復(fù)雜的異步操作,就要使用者兩類異步函數(shù)作為基本的構(gòu)造快。本文沒有對某個知識點(diǎn)...
摘要:生成器是原生提供的異步編程方案,其語法行為和傳統(tǒng)函數(shù)完全不同,阮大的入門一書中對生成器有比較詳盡的介紹,還有一些其他的文章可以參考,比如入門深入淺出三生成器深入淺出十一生成器,續(xù)篇本文主要是通過一些代碼示例來記錄和總結(jié)生成器的用法。 Generator 生成器是es6原生提供的異步編程方案,其語法行為和傳統(tǒng)函數(shù)完全不同,阮大的《ECMAScript 6 入門》一書中對生成器有比較詳盡的...
摘要:更好的異步編程上面的方法可以適用于那些比較簡單的異步工作流程。小結(jié)的組合目前是最強(qiáng)大,也是最優(yōu)雅的異步流程管理編程方式。 訪問原文地址 generators主要作用就是提供了一種,單線程的,很像同步方法的編程風(fēng)格,方便你把異步實現(xiàn)的那些細(xì)節(jié)藏在別處。這讓我們可以用一種很自然的方式書寫我們代碼中的流程和狀態(tài)邏輯,不再需要去遵循那些奇怪的異步編程風(fēng)格。 換句話說,通過將我們generato...
閱讀 796·2021-11-24 09:38
閱讀 998·2021-11-11 11:01
閱讀 3236·2021-10-19 13:22
閱讀 1524·2021-09-22 15:23
閱讀 2828·2021-09-08 09:35
閱讀 2766·2019-08-29 11:31
閱讀 2119·2019-08-26 11:47
閱讀 1563·2019-08-26 11:44