国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

簡單理解Javascript的各種異步流程控制方法

makeFoxPlay / 2381人閱讀

摘要:所以僅用于簡化理解,快速入門,依然需要閱讀有深入研究的文章來加深對各種異步流程控制的方法的掌握。

原文地址:http://zodiacg.net/2015/08/javascript-async-control-flow/

隨著ES6標準逐漸成熟,利用Promise和Generator解決回調地獄問題的話題一直很熱門。但是對解決流程控制/回調地獄問題的各種工具認識仍然比較麻煩。最近兩天看了很多文章,想出幾個場景把各種異步流程方式類比一下,希望能有助于理解他們的實現。

需要說明的是類比只能反映被類比的事物的一個方面,必然有其反映不到的部分,不能完全以類比來理解各種異步控制的本質。所以僅用于簡化理解,快速入門,依然需要閱讀有深入研究的文章來加深對各種異步流程控制的方法的掌握。

文章中沒有嚴格使用Node.js核心模塊的函數名,而是偽造的函數名來方便在各種方式下保持一致性和簡化書寫。

同步

從最簡單的同步開始。以一段經典的代碼為例吧,傳入文件名,從文件中讀取內容并按JSON格式解析,把其中的一部分內容發還給用戶。

function foo(filename){
    var file = readFile(filename);
    var json = parseJSON(file);
    return json.someContent;
}

var resultA=foo("first.json");
var resultB=foo("second.json");

其中readFileparseJSON顯而易見是同步、阻塞的函數。

我們構造這樣一個場景,M(ain)代表著解釋引擎的主線程,坐在柜臺前等待用戶提交請求。

來了兩個用戶A和用戶B,用戶A排在前面。

用戶A: 你好,我要讀文件first.json
M:好的你等一下我去拿。
【M離開了柜臺去拿文件】
M:好的我回來了,這是你要的first.json的內容。然后呢?
用戶A:然后把內容按JSON解析一下。
M:你等等我去解析一下。
【M離開了柜臺去解析文件內容】
M:好了解析完了,然后呢?
用戶A:我要里面的someContent部分。
M:給你。再見。

用戶B:你好,我要讀文件second.json。
…………

可以看到同步阻塞顧名思義,操作一步一步進行,遇到IO操作每一步都要等待,用戶A不處理完,用戶B也進不來。

經典回調方式

仍然是這個需求,這次的代碼就比較像Node.js里的常見形式了,此處為了簡單忽略了err。由于回調套回調,縮進如同金字塔,被稱作回調地獄。當然回調地獄遠不是一個縮進金字塔那么簡單。

function foo(filename, cb){
    readFile(filename,function(file){
        parseJSON(file,function(json){
            cb(json.someContent);
        });
    });
}

foo("first.json",cbA);
foo("second.json",cbB);

依然是來了兩個用戶A和用戶B

用戶A:你好,我要讀文件first.json,按JSON解析后把里面的someContent寄往cbA發回給我。
M:好的。
【M開始寫信,信封上寫上文件讀取處readFile,拿出一張信紙寫到:“讀取first.json,然后內容放進后附信封中寄出”?!?
【M又拿出一個信封,寫上JSON解析處parseJSON,信紙上寫到“把給你的file按JSON解析,然后把里面的someContent放到所附信封里寄出”。】
【M又又拿出一個信封,寫上cbA,然后把這個信封放進了剛才的信封里,又把剛才的信封塞進了第一個信封里?!?
【M把鼓鼓囊囊的信封扔到郵箱里就不管了】
M:下一位!
用戶B:你好……

寫幾封信的時間比自己跑出去取文件要快的多。異步操作帶來的處理速度提升是顯而易見的。

但是為了保證業務流程的銜接,信里面就包含了后續一切需要進行的操作,層層包裹。第一封信寄出,M就既無從得知信走到了何處,也無法控制readFileparseJSON是不是如自己所想寄出了給他的信封,有沒有私自復印了多寄了一兩封。

這才是回調地獄真正危險的地方,缺乏控制。

Promise

引入Promise之后,很多人就以為能解決回調地獄了,其實不然。在某些場景下只是讓縮進好看了一點而已。有些場景下縮進也沒法好看,需要書寫的回調不僅不會減少還會增多。

function foo(filename,cb){
    readFile(filename)
    .then(parseJSON(file))
    .then(function(json){
    cb(json.someContent)});
}

foo("first.json",cbA);
foo("second.json",cbB);

當然這里面的readFileparseJSON已經是Promise化了的。

依然是來了兩個用戶A和用戶B

用戶A:你好,我要讀文件first.json,按JSON解析后把里面的someContent寄往cbA發回給我。
M:好的。
【M叫來了一個辦事員小P】
M:小P你聽好,先去找readFile讀取first.json,然后把內容給parseJSON讓他解析一下,最后把解析的內容里的someContent寄給cb,懂了嗎?
P:我辦事你放心!
【小P離開了柜臺】
M:下一位!
用戶B:你好……

小P是一位M信得過的辦事員,M相信他能夠挨個去找該找的部門,不偷工減料也不毛手毛腳。讓小P去辦事比寄一封信靠譜的多,M依然能很快回過頭來繼續應付下一個用戶請求。

當然實際場景中雖然寫的時候.then一下子連起來寫完,并不是真的一下子把內容都交給同一位小P/同一個Promise。更像是一個Promise公司,每個操作進行完后都由一位Promise公司的辦事員進行下一步操作。

Promise物如其名,使用Promise重要的就是Promise的可信性,比如Promise的狀態不可逆,比如fulfill回調只會被調用一次。Promise并不是回避書寫回調,而是用一種更可靠的方式來書寫回調。

Co(Generator)

這里只談co不談Generator,是因為Generator并不是為解決異步流程控制而生的,而TJ大神用co把Generator和Thunk/Promise結合在一起提供了新的異步流程控制的方法。

var foo=co(function*(filename){
    var file = yield readFile(filename);
    var json = yield parseJSON(file);
    return json.someContent;
});

foo("first.json").then(cbA);
foo("second.json").then(cbB);

咦?這代碼看起來跟同步的怎么差不多。

這次我們換個方法描述,一樣是來了用戶A和用戶B,但是先從用戶A的視角來看這件事情。

用戶A: 你好,我要讀文件first.json。
M:好的你等一下我去拿。
【M離開了柜臺】
M:我回來了,這是你要的first.json的內容。然后呢?
用戶A:然后把內容按JSON解析一下。
M:你等等我去解析一下。
【M離開了柜臺】
M:好了解析完了,然后呢?
用戶A:我要里面的someContent部分。
M:給你。再見。

是不是看起來跟同步一模一樣?實際上從M的角度看這件事情呢?

用戶A: 你好,我要讀文件first.json。
M:好的你等一下我去拿。
【M離開了柜臺】
M:小P來一下!去readFilefirst.json,回來叫我。
P:好的我這就去。
【M轉向了另一個柜臺窗口】
M:你好。
用戶B:你好,我要讀文件second.json
…………
…………
P:M,first.json拿回來了。
【M轉向第一個柜臺】
M:我回來了,這是你要的first.json的內容。然后呢?
用戶A:然后把內容按JSON解析一下。
M:你等等我去解析一下。
【M離開了柜臺】
M:小P來一下!去parseJSON把這堆東西解析一下,回來叫我。
P:好的我這就去。
【M轉向了另一個柜臺窗口】
…………
…………

真相大白了,M并沒有親自去拿文件解析JSON,而是叫來了任勞任怨的小P干活,自己在用戶A面前偽裝成被占用了所有的時間的樣子,其實偷偷去接待別的用戶了。

利用Generator可以用yield中斷執行,再在外部通過next喚醒繼續執行的特性,co把Generator的next寫到Promise的then里面從而實現循環調用。使用了co之后,代碼看起來跟同步非常相像,寫起來符合人正常的同步思維,甚至可以使用同步的流程控制語句比如for。但是執行起來卻能充分利用異步帶來的性能優勢。

順便提一句,co看起來已經非常像async/await方式了。Node.js中同樣近似于async/await方式的還有asyncawait庫,它不依賴generator而是依賴于node-fiber,看名字大概就是Node里的一個纖程的實現吧。由于不需要generator,對于諸如Coffescript和Typescript類的語言支持非常好。

以上就是對Javascript中最近常討論的幾種異步流程控制的簡單類比說明。這種理解方式非常粗淺,而且有很多問題并不像上面寫的那樣那么簡單。要想使用好異步,還是要多讀一些更為深入的文章。

參考資料

Promises and Generators: Control Flow Utopia

Promises/A+

Managing Node.js Callback Hell with Promises, Generators and Other Approaches

Replacing callbacks with ES6 Generators

getiblog: Promises

異步流程控制:7 行代碼學會 co 模塊

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/85899.html

相關文章

  • JavaScript 異步

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

    tuniutech 評論0 收藏0
  • javascript異步編程詳解

    摘要:在服務器端,異步模式甚至是唯一的模式,因為執行環境是單線程的,如果允許同步執行所有請求,服務器性能會急劇下降,很快就會失去響應。第三是,捕捉不到他的錯誤異步編程方法回調函數這是異步編程最基本的方法。 前言 你可能知道,Javascript語言的執行環境是單線程(single thread)。所謂單線程,就是指一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成,再執行后面...

    huangjinnan 評論0 收藏0
  • 【全文】狼叔:如何正確學習Node.js

    摘要:感謝大神的免費的計算機編程類中文書籍收錄并推薦地址,以后在倉庫里更新地址,聲音版全文狼叔如何正確的學習簡介現在,越來越多的科技公司和開發者開始使用開發各種應用。 說明 2017-12-14 我發了一篇文章《沒用過Node.js,就別瞎逼逼》是因為有人在知乎上黑Node.js。那篇文章的反響還是相當不錯的,甚至連著名的hax賀老都很認同,下班時讀那篇文章,竟然坐車的還坐過站了。大家可以很...

    Edison 評論0 收藏0
  • 【全文】狼叔:如何正確學習Node.js

    摘要:感謝大神的免費的計算機編程類中文書籍收錄并推薦地址,以后在倉庫里更新地址,聲音版全文狼叔如何正確的學習簡介現在,越來越多的科技公司和開發者開始使用開發各種應用。 說明 2017-12-14 我發了一篇文章《沒用過Node.js,就別瞎逼逼》是因為有人在知乎上黑Node.js。那篇文章的反響還是相當不錯的,甚至連著名的hax賀老都很認同,下班時讀那篇文章,竟然坐車的還坐過站了。大家可以很...

    fengxiuping 評論0 收藏0

發表評論

0條評論

makeFoxPlay

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<