《Nodejs開發加密貨幣》之十一:一張圖熟練使用Async組件解決回調大坑

關於

《Nodejs開發加密貨幣》,是一個加密貨幣產品的詳細開發文檔,涉及到使用Nodejs開發產品的方方面面,從前端到後臺、從服務器到客戶端、從PC到移動、加密解密等各個環節。代碼完全開源、文章免費分享。 相關資源見 http://ebookchain.org

前言

前面說過,在Nodejs的世界裏“事事皆回調”,學習使用Nodejs,最不可能迴避的就是“回調”(用“調回”更直觀些)。無法迴避,自然要積極面對,因此開源社區出現了很多代碼流程控制的解決方案。比如:bluebird,q,以及這裏要圖解的async。

這種基礎性的技術,社區的文檔極其豐富,顯然我們沒必要重複前人,所以這裏採取圖解和歸類的形式,從操作方面入手。另外,細心的朋友也會從前面的源碼分析中發現,億書大量使用了aysnc,全面掌握它,對於理解和編碼,事倍功半。

most-depended-upon-packages.jpg

這是async在https://npmjs.org上的排名,除了lodash,就是它了。而且,bluebird和q也都在前10,也基本說明,使用流程控制組件是Nodejs處理回調的標配。

概念定義

官方介紹:

Async is a utility module which provides straight-forward, powerful functions for working with asynchronous JavaScript.

簡單翻譯:Async是一個爲處理異步Js提供簡單、直接、強大功能的實用模塊。

流程類別

僅僅爲了好區分、好記憶,簡單彙總一下,全部流程應該是下面三種情況(並非官方描述):

1.基本流程

從程序(多個函數)執行順序的角度考量,包括順序執行、並行執行、混合執行等基本流程。如果把函數間是否有依賴、是否限制函數執行的數量等,又可繼續演化出很多種。

2.循環流程

基於某個條件的循環操作,根據條件使用方式,提供了諸多函數。

3.集合流程

上面都是針對一個或一組數據的處理。現實中,通常要對大批相同或相似的數據,比如:大批文件、地址,進行集中處理。顯然,我們第一反應是循環調用上述流程即可,不過Async提供了對集合進行異步操作的工具方法(util),如forEach等,就叫它“集合流程”吧。

使用流程的概念可以明確告訴我們,當使用async.forEach()的時候,是在異步操作,與單純的forEach方法調用是有區別的。

用法分類

async提供了70多個實用的函數,所有這些函數都遵守一個約定:你定義的異步函數(當作一個任務),最後一個參數必須是callback函數;該callback函數的第一個參數必須是Error,且callback函數調用一次。

這些函數大致分爲3類,分別對應上面的3個類別:

1.基本型(一次多任務)

這對應基本流程和演化流程部分,對一項事務,多個任務的操作,調用形式爲

async.funName(tasks, callback(error, results))

這裏的funName,包括:series, parallel(parallelLimit), waterfall, auto(autoInject)等。這裏的tasks可以是Array形式,也可以是Json形式,或者僅支持其中一種。

如果全部函數執行成功,callback裏的results也會對應tasks的形式,將已經執行函數的結果轉化爲Array或Json形式;如果tasks中有一個函數出錯,就會終止後續執行,調用callback,error就是該函數的錯誤信息,results或僅包含已經執行的結果、或同時包含未執行函數的結果佔位符,或什麼都不包含直接忽略。至於results具體是什麼,一個log語句,自然就能知曉,不必去查文檔。

2.循環型(多次單任務)

根據條件不同,可以使用下面的形式調用

async.funName(test, fn, callback)

或

async.doFunName(fn, test, callback)

這裏的funName,包括:whilst(doWhilst),until(doUntil), during(doDuring), retry(retryable),times(timesSeries, timesLimit)、forever(該函數的條件test就不用了,已經暗含條件)。

這裏的條件值可以是表達式函數,或具體的次數。區分fn與test的順序,很簡單,只要用英文的意思去理解就可以,比如:async.doWhilst(),必然是先do,後whilst,因此參數自然是async.doWhilst(fn, test, callback)

3.集合型(多次單任務)

這個官方沒有當作流程表述,當作集合操作方法提供的,是我個人的理解和杜撰。我覺得把它歸爲流程控制更好接受和理解。因此,仿造上面的循環型調用方法,只要將條件test改爲一個集合就好,集合全部使用數組array形式。

async.funName(arr, iteratee, [callback])

這裏的funName,包括:

each, eachSeries, eachLimit
forEachOf, forEachOfSeries, forEachOfLimit
map, mapSeries, mapLimit
filter, filterSeries, filterLimit
reject, rejectSeries, rejectLimit
reduce, reduceRight
detect, detectSeries, detectLimit
sortBy
some, someLimit, someSeries
every, everyLimit, everySeries
concat, concatSeries

當然,async還明確提供了其他幾個流程控制,比如:compose,seq,applyEach(applyEachSeries),queue(priorityQueue),cargo,iterator,race等。

另外,還有幾個Util(工具)函數,如:apply,nextTick,memoize,unmemoize,ensureAsync,constant,asyncify,wrapSync,log,dir,noConflict,timeout等,這些都能極大的方便代碼撰寫,改善代碼性能。

腦圖

上述解釋和方法,我們全部放在一張腦圖裏,結合場景,按圖索驥,能夠很快找到正確的處理方法。

Nodejs流程控制組件Async全解.png

源碼解讀

看看Ebookcoin裏面,async的使用吧。因爲在《入口程序app.js解讀》裏,已經提及,這裏就不說了,以後遇到再解釋。

async-in-ebookcoin.jpg

趣味實踐

Async官方文檔提供了很多實例, 簡單直觀。這裏,我們不再舉例,而是提出一個趣味問題,供思考:

問題:Aysnc能否用於遞歸調用,比如:某個爬蟲程序,遍歷某文件夾下全部文件信息的函數等?爲什麼?

總結

這又是一篇老生常談的技術分享,但寫完之後,對異步操作的流程管理,更加清晰了。Aysnc很好,但也不是萬能的,它對於那些反覆自調用的代碼就無能爲力,因爲限制任務的回調就是一次。後續,有機會還會繼續深入學習研究它。

鏈接

本系列文章即時更新,若要掌握最新內容,請關注下面的鏈接

本源文地址: https://github.com/imfly/bitcoin-on-nodejs

電子書閱讀: http://bitcoin-on-nodejs.ebookchain.org

參考

async官方文檔

Node.js最新技術棧之Promise篇

JavaScript Promise迷你書(中文版)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章