成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

用co玩轉(zhuǎn)異步

microelec / 2170人閱讀

摘要:否則不會(huì)得到異步之后的值對(duì)象的值,并沒(méi)有在中進(jìn)行處理,而是直接作為返回值返回到對(duì)象外面了這就是的魔法。當(dāng)生成器函數(shù)內(nèi)的邏輯執(zhí)行完畢且沒(méi)有錯(cuò)誤之后,這個(gè)對(duì)象返回值變?yōu)闋顟B(tài),且將生成器的返回值作為出來(lái)的值。

之前我在關(guān)于Promise的文章中提到了co這個(gè)庫(kù)。在這篇文章里,我將寫(xiě)一寫(xiě)自己對(duì)它的認(rèn)識(shí)。

Trust me,用了co庫(kù),你不想用別的,來(lái)它半斤異步調(diào)用你一口能吃仨。

但是我對(duì)Tj大神的co庫(kù)源碼談不上深入理解。所以,如有亂講,歡迎指正。

我這里默認(rèn)讀者對(duì)PromiseGenerator有一定的認(rèn)識(shí)。

先安利自己寫(xiě)的兩篇關(guān)于Promise的文章:

淺析ES6原生Promise

再談Promise

下面我就來(lái)談?wù)?b>co這個(gè)牛逼的庫(kù)。

ES7 async/await

干嘛,我們不是講ES6么,怎么跳到ES7了?

因?yàn)?b>co要做的事情,就是ES7的async/await要做的事情。
也就是說(shuō),這種解決異步的思路,已經(jīng)在ECMA標(biāo)準(zhǔn)的考慮之中了。將來(lái)我們?yōu)g覽器的JS引擎就可以原生實(shí)現(xiàn)這件事而不是通過(guò)JavaScript代碼模擬。要知道,引擎的實(shí)現(xiàn)和代碼的實(shí)現(xiàn)那是完全兩碼事。

一點(diǎn)題外話(huà)

多一句嘴:有些同學(xué)混淆了ECMA標(biāo)準(zhǔn)、引擎支持和代碼實(shí)現(xiàn)的聯(lián)系。

這里引用老趙在知乎里面回答問(wèn)題時(shí)說(shuō)的一句話(huà):

ES7是個(gè)標(biāo)準(zhǔn),定義的是what to do不是how to do,為什么好多人還是搞不清這兩者的區(qū)別。

ECMAScript定義了一些JavaScript語(yǔ)言層面要做的事情,這是一個(gè)標(biāo)準(zhǔn)。之所以要制定這個(gè)標(biāo)準(zhǔn),是為了防止瀏覽器各自為政而出現(xiàn)JS引擎對(duì)同一行代碼的解釋出現(xiàn)不同的情況。

也就是說(shuō),ECMA制定標(biāo)準(zhǔn),我們就可以按照這個(gè)標(biāo)準(zhǔn)來(lái)寫(xiě)JavaScript代碼。寫(xiě)好的JavaScript代碼由瀏覽器的JS引擎來(lái)解釋?zhuān)罱K變成計(jì)算機(jī)能讀懂的代碼來(lái)執(zhí)行。

async/await

上代碼:

var foo = function(){

    return new Promise(resolve => {
        // 異步操作之后
        resolve("OK");
    });
}

async funtion bar(){
    
    var result = await foo();
    
    console.log(result); 
    
}

bar(); // ==> 打印"OK"

我們注意到,這段代碼用了兩個(gè)新的關(guān)鍵字asyncawait。而且有兩件神奇的事情發(fā)生了:

bar函數(shù)中包含了一個(gè)返回Promise對(duì)象的語(yǔ)句,而且Promise中存在異步代碼。但是這條語(yǔ)句接下來(lái)的語(yǔ)句明顯是等待Promise對(duì)象中的代碼異步執(zhí)行完畢之后才執(zhí)行的。(否則不會(huì)得到異步之后的值)

Promise對(duì)象resolve的值,并沒(méi)有在then中進(jìn)行處理,而是直接作為返回值返回到Promise對(duì)象外面了.

這就是async/await的魔法。在函數(shù)前面加上async關(guān)鍵字之后,內(nèi)部的代碼會(huì)識(shí)別await關(guān)鍵字。此時(shí)假設(shè)await后面的語(yǔ)句返回一個(gè)Promise對(duì)象,那么執(zhí)行的代碼將會(huì)等待,直到Promise對(duì)象變?yōu)?b>resolve狀態(tài)。并且Promise對(duì)象中resolve的值將直接作為await語(yǔ)句的返回值返回。然后再執(zhí)行await語(yǔ)句之后的語(yǔ)句。

從此我們就可以無(wú)痛的擼異步代碼,媽媽再也不用擔(dān)心回調(diào)金字塔的出現(xiàn)和異步流程邏輯搞不定的情況了!

另一個(gè)奇妙的事情就是,率先支持這一特性的瀏覽器居然是微軟的Edge。大概是因?yàn)?b>C#語(yǔ)言早就出現(xiàn)async/await,并且TypeScript也支持這一特性的緣故吧。

co

我們希望所有的瀏覽器都及早支持這一特性。但是值得欣喜的一點(diǎn)就是,雖然V8還沒(méi)有支持,Tj大神早就利用Generator的方式實(shí)現(xiàn)了一個(gè)ES6版本的async/await!(膜拜臉)

co函數(shù)形式

同樣是上面的邏輯,我們用co實(shí)現(xiàn)一次:

// 首先我們需要將co引入,假設(shè)我們使用commonJS的方式  

const co = require("co");

var foo = function(){

    return new Promise(resolve => {
        // 異步操作之后
        resolve("OK");
    });
}

co(function* (){
    
    var result = yield foo();
    
    console.log(result); 
    
}); // ==> 打印"OK"

我們看到,co函數(shù)接收一個(gè)Generator生成器函數(shù)作為參數(shù)。執(zhí)行co函數(shù)的時(shí)候,生成器函數(shù)內(nèi)部的邏輯像async函數(shù)調(diào)用時(shí)一樣被執(zhí)行。不同之處只是這里的await變成了yield。

簡(jiǎn)單版本的co代碼

要實(shí)現(xiàn)以上的邏輯,結(jié)合Generator的特性,co函數(shù)應(yīng)該:

在函數(shù)體內(nèi)將Generator生成器函數(shù)執(zhí)行并生成生成器實(shí)例(在此命名為gen),然后通過(guò)gen.next方法的調(diào)用,不斷執(zhí)行生成器函數(shù)內(nèi)部的代碼。

執(zhí)行next方法之后,返回的Promise在生成器函數(shù)執(zhí)行環(huán)境之外執(zhí)行,并取出resolve值,作為返回值作為next方法的參數(shù)返回到Generator執(zhí)行環(huán)境中。

基于以上兩點(diǎn),我們可以大體實(shí)現(xiàn)一個(gè)簡(jiǎn)化版的co,代碼如下:

const co = function(genFunc){  
    const gen = genFunc(); // 得到生成器實(shí)例  
    
    const deal = (val) => {
        
        const res = gen.next(val); 
        
        // 這里處理了異步邏輯,
        // 在回調(diào)中去遞歸,不斷執(zhí)行next
        // 這樣就將resolve的值傳回了Generator
        res.value.then(result => deal(result));
        
    }
    
    deal(); // 第一次觸發(fā)遞歸
}

去掉括號(hào)等等,只有短短六行代碼。

more

原理性的東西大約就是這樣了。但是co做的不止這些。

之前coyield后的語(yǔ)句并不支持Promise對(duì)象,而是一個(gè)特殊的函數(shù),叫做thunk。目前co二者都支持。
此處我并不打算重復(fù)性解釋thunk版本,因?yàn)樵硇缘臇|西實(shí)現(xiàn)起來(lái)是差不多的。

co函數(shù)是有返回值的,也是一個(gè)Promise對(duì)象。

當(dāng)生成器函數(shù)內(nèi)的邏輯執(zhí)行完畢且沒(méi)有錯(cuò)誤之后,這個(gè)Promise對(duì)象(co返回值)變?yōu)?b>resolve狀態(tài),且將生成器的返回值作為resolve出來(lái)的值。

若生成器函數(shù)內(nèi)返回一個(gè)Promise對(duì)象,那么co函數(shù)返回值就是這個(gè)Promise對(duì)象。

若生成器函數(shù)拋出了錯(cuò)誤,那么這個(gè)錯(cuò)誤作為reject出來(lái)的值,將Promise對(duì)象的狀態(tài)變?yōu)?b>reject。

這樣我們就可以將錯(cuò)誤放進(jìn)其返回值的.catch方法中統(tǒng)一處理。

在生成器函數(shù)內(nèi)部,我們也可以使用try...catch語(yǔ)句獲取錯(cuò)誤對(duì)象。

生成器的yield后面可以跟一個(gè)元素值為Promise對(duì)象的數(shù)組,這個(gè)數(shù)組內(nèi)Promise對(duì)象內(nèi)的異步邏輯將并發(fā)執(zhí)行,并返回一個(gè)數(shù)組。(類(lèi)似于Promise.all方法)

假設(shè)生成器執(zhí)行之前需要從外部傳入?yún)?shù),co庫(kù)提供了一個(gè)方法:

  var fn = co.wrap(function* (val) {
  
     return yield Promise.resolve(val);

  });

  fn(true).then(function (val) {

  });
結(jié)束

以上是一點(diǎn)微小的見(jiàn)解。謝謝指正。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80191.html

相關(guān)文章

  • JavaScript 異步

    摘要:從最開(kāi)始的到封裝后的都在試圖解決異步編程過(guò)程中的問(wèn)題。為了讓編程更美好,我們就需要引入來(lái)降低異步編程的復(fù)雜性。寫(xiě)一個(gè)符合規(guī)范并可配合使用的寫(xiě)一個(gè)符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來(lái)處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問(wèn)題描述 在開(kāi)發(fā)過(guò)程中,遇到一個(gè)需求:在系統(tǒng)初始化時(shí)通過(guò)http獲取一個(gè)第三方服務(wù)器端的列表,第三方服務(wù)器提供了一個(gè)接口,可通過(guò)...

    tuniutech 評(píng)論0 收藏0
  • 玩轉(zhuǎn)Koa -- koa-bodyparser原理解析

    摘要:主要通過(guò)處理二進(jìn)制數(shù)據(jù)流,但是它并不支持字符編碼方式,需要通過(guò)模塊進(jìn)行處理。最后留圖一張往期精彩回顧玩轉(zhuǎn)原理解析玩轉(zhuǎn)核心原理分析 一、前置知識(shí) ??在理解koa-bodyparser原理之前,首先需要了解部分HTTP相關(guān)的知識(shí)。 1、報(bào)文主體 ??HTTP報(bào)文主要分為請(qǐng)求報(bào)文和響應(yīng)報(bào)文,koa-bodyparser主要針對(duì)請(qǐng)求報(bào)文的處理。 ??請(qǐng)求報(bào)文主要由以下三個(gè)部分組成: 報(bào)文頭...

    andycall 評(píng)論0 收藏0
  • 【全文】狼叔:如何正確的學(xué)習(xí)Node.js

    摘要:感謝大神的免費(fèi)的計(jì)算機(jī)編程類(lèi)中文書(shū)籍收錄并推薦地址,以后在倉(cāng)庫(kù)里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡(jiǎn)介現(xiàn)在,越來(lái)越多的科技公司和開(kāi)發(fā)者開(kāi)始使用開(kāi)發(fā)各種應(yīng)用。 說(shuō)明 2017-12-14 我發(fā)了一篇文章《沒(méi)用過(guò)Node.js,就別瞎逼逼》是因?yàn)橛腥嗽谥跎虾贜ode.js。那篇文章的反響還是相當(dāng)不錯(cuò)的,甚至連著名的hax賀老都很認(rèn)同,下班時(shí)讀那篇文章,竟然坐車(chē)的還坐過(guò)站了。大家可以很...

    Edison 評(píng)論0 收藏0
  • 【全文】狼叔:如何正確的學(xué)習(xí)Node.js

    摘要:感謝大神的免費(fèi)的計(jì)算機(jī)編程類(lèi)中文書(shū)籍收錄并推薦地址,以后在倉(cāng)庫(kù)里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡(jiǎn)介現(xiàn)在,越來(lái)越多的科技公司和開(kāi)發(fā)者開(kāi)始使用開(kāi)發(fā)各種應(yīng)用。 說(shuō)明 2017-12-14 我發(fā)了一篇文章《沒(méi)用過(guò)Node.js,就別瞎逼逼》是因?yàn)橛腥嗽谥跎虾贜ode.js。那篇文章的反響還是相當(dāng)不錯(cuò)的,甚至連著名的hax賀老都很認(rèn)同,下班時(shí)讀那篇文章,竟然坐車(chē)的還坐過(guò)站了。大家可以很...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<