国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

從零學習node.js之詳解異步控制工具async(八)

2019-11-19 17:24:44
字體:
來源:轉載
供稿:網友

前言

大家在編寫異步程序時,最頭痛的就是不知道結果什么時候返回給我們,然后執行后面的操作,很多時候只能把后面的操作放到返回成功的函數里,或者使用計數器等方法。

比較典型的兩個就是:后面的操作需要依賴上一個異步操作的結果;多個異步操作并行執行,都執行完成后再執行接下來的操作。

這兩個操作中,第一個異步的程序我們可能會寫成這樣:

db.select(SQL1, function(res1){ db.delete(SQL2, function(res2){ db.insert(SQL3, function(res3){ // ... }) })});

將后面的操作寫到執行成功后的回調函數里。第2個并行的異步操作,可以使用計數器的方法,每個異步調用成功時,計數器加1,當所有的異步都調用成功后,再接著執行:

var count = 0;var success = function(){ count++; if(count>=3){   console.log('執行完畢...'); }}var select = function(){ db.select(sql, function(res){  success(); })}var select2 = function(){ db.select(sql, function(res){  success(); })}var select3 = function(){ db.select(sql, function(res){  success(); })}select();select2();select3();

這些編寫方式非常麻煩,而且代碼邏輯比較混亂,調試起來也很不方便。那么就要用到異步控制的利器async了。

介紹

async的作用是進行流程的控制,而且提供了非常多的方法可供調用。

這些方法可以分為三大類:

  • 集合類(Collections)
  • 流程控制類(Control Flow)
  • 工具類(Utils)

下面我們從這三個分類里分別挑出幾個方法進行講解。

二、函數介紹

async中提供了非常多的方法可供使用,我們僅僅是講解其中幾個比較有代表性的,其他的可以訪問官方文檔:http://caolan.github.io/async/docs.html。

2.1 集合類

集合類中的方法主要有some, ‘map', ‘each', ‘every'等,這些方法是對數組或組合進行某個相同的操作后,統一執行回調函數。

我們以map為例,map對集合中的每一個元素,執行某個相同的異步操作,得到結果。所有的結果將匯總到最終的callback里。
使用方法,map接收三個參數,分別是:

參數名稱 類型 說明
coll iteratee callback
Array | Iterable | Object function function
需要處理數組,集合或其他可迭代的類型 迭代方法,用來對集合中的每一項進行處理。該方法接收兩個參數(item, callback);item為集合中的每一項, callback為回調函數。callback需要帶有err(有時可能為null)和處理后的數據,callback(err, data) 最終回調函數,當集合處理完畢后調用此函數,傳遞兩個參數err和result,result為之前處理后的所有的結果的集合

注意:中間處理函數iteratee對coll中的每一項都是并發處理的,因此并不能保證iteratee按照順序完成。不過,如果coll是個數組,最后的結果集results會按照coll中的順序排列;如果coll是個集合(Object)類型,results會是數組類型,結果將大致按照coll的鍵的順序排列(但是不同在不同的JavaScript引擎中會有可能發生變化)。

我們來舉個例子,使用map獲取幾個文件中的內容:

var files = ['./file/cnode_1.txt', './file/cnode_2.txt', './file/cnode_3.txt'];// 讀取文件內容// 第1個參數 文件名稱列表的數組// 第2個參數 傳入數組中的每一項和回調函數// 第3個參數 results為所有結果的集合async.map(files, function(file, cb){ fs.readFile(file, 'utf-8', function(err, data){  cb(err, data); })}, function(err, results){ console.log( results );})

而且,如果中間的處理函數比較大,不想寫在map中,也可以單獨寫成一個函數,然后傳遞進去,不過參數傳遞還是要符合規則的:

var files = ['./file/cnode_1.txt', './file/cnode_2.txt', './file/cnode_3.txt'];var read = function(file, cb){ fs.readFile(file, 'utf-8', function(err, data){  cb(err, data); })}async.map(files, read, function(err, result){ console.log( result );})

這里還有一個mapLimit,可以傳遞一個參數limit,用來限制并發的數量:mapLimit(coll, limit, iteratee, callbackopt)

// 并發數量為2async.mapLimit(files, 2, read, function(err, result){ console.log( result );})

同時,集合類中還有其他的方法,我們也稍微了解下:

  1. each : 與map類似,但是最后的回調函數里沒有results,each只循環不負責處理結果
  2. every : 中間處理函數iteratee的參數(err, boolean)需要傳遞一個boolean值,若所有選項的結果都為true,則results為true
  3. some : 與every類似,只是只要其中一個選項的結果為true,則results為true
  4. filter : 對coll進行篩選,篩選出結果為true的結果
  5. reject : 與filter正好相反,篩選出結果為false的結果
  6. concat : 將每個異步操作的結果合并為一個數組

2.2 流程控制類

上面的集合類是對一個集合進行相同的處理,集合中的每一項都處理完后,再對結果進行回調處理。而多個回調方法執行時,則需要對這幾個回調方法進行控制了。

多個回調方法執行時,通常有這么幾個流程:

  1. 串行且無關聯,即執行完一個后再依次執行下一個,且相互之間無數據交互,都執行完后,再執行最后的回調函數。可以使用async.series
  2. 串行且有關聯,即執行完一個后再依次執行下一個,且上一個回調函數的結果會作為下一個回調函數的參數。可以使用async.waterfall
  3. 并行,這幾個回調函數同時并發執行,都執行完成后,再執行最后的回調函數。可以使用async.parallel

當然還有其他更復雜的流程,這里也只聊上面的三種情況。

async.series,async.waterfall和async.parallel的語法都是一樣的:async.Method(coll, function(err, results){})

其中coll既可以是數組,也可以是json格式的,而且results的類型與coll對應。

串行且無關聯async.series

// 串行且無關聯,數組格式async.series([ function(cb){  getAllList(function(result){   cb(null, result);  }); }, function(cb){  getAllUser(function(result){   cb(null, result);  }); }], function(err, result){ console.log(result);})

同時串行的異步可以是json格式的:

// 串行且無關聯,json個數async.series({ one: function(cb){  getAllList(function(result){   cb(null, result);  }); }, two: function(cb){  getAllUser(function(result){   cb(null, result);  }); }}, function(err, result){ console.log(result);})

串行且有關聯async.waterfall

// 串行且上一個結果作為下一個的參數async.waterfall([ function(cb){  getListById(1, function(result){   cb(null, result);  }); }, function(params, cb){  console.log(params);  getAllUser(function(result){   cb(null, result);  }); }], function(err, result){ console.log(result);})

并行async.parallel

// 并行,getAllList與getAllUser同時執行async.parallel([ function(cb){  getAllList(function(result){   cb(null, result);  }); }, function(cb){  getAllUser(function(result){   cb(null, result);  }); }], function(err, result){ console.log(result);})

關于并行的異步操作,這里還有一個async.parallelLimit,限制并發的數量:

// 并發數量為2async.parallelLimit([ iteratee1, iteratee2, iteratee3, ...], 2, function(err, results){ })

2.3 工具類

async中也提供了不少的工具方法可供使用,比如async.log可以輸出回調方法中的值,第1個參數為函數,后面的參數為傳遞給函數的參數:

var hello = function(name, callback) { setTimeout(function() {  callback(null, 'hello ' + name); }, 1000);};// 將'world'傳遞給hello方法async.log(hello, 'world'); // 'hello world'

這里面還有apply, dir, timeout等方法。

總結

使用async控制異步流程非常的方便,而且也可以在前端使用,比如可以操作多個ajax請求等。好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 宁阳县| 萨嘎县| 武威市| 沾化县| 凌源市| 大荔县| 宁蒗| 阳泉市| 福贡县| 内乡县| 乐安县| 九寨沟县| 台前县| 蓝山县| 昭苏县| 亚东县| 巴东县| 广昌县| 邳州市| 方城县| 桐城市| 基隆市| 温州市| 比如县| 桂阳县| 雷山县| 济阳县| 彝良县| 航空| 河北省| 那坡县| 凌云县| 香港| 惠东县| 施秉县| 韶山市| 棋牌| 汉阴县| 富裕县| 驻马店市| 柏乡县|