亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript異步編程:異步數(shù)據(jù)收集的具體方法

 更新時(shí)間:2013年08月19日 16:02:09   作者:  
我們先嘗試在不借助任何工具函數(shù)的情況下來(lái)解決這個(gè)問(wèn)題。筆者能想到的最簡(jiǎn)單的方法是:因前一個(gè)readFile的回調(diào)運(yùn)行下一個(gè)readFile,同時(shí)跟蹤記錄迄今已觸發(fā)的回調(diào)次數(shù),并最終顯示輸出。下面是筆者的實(shí)現(xiàn)結(jié)果。

Asyncjs/seriesByHand.js

復(fù)制代碼 代碼如下:

var fs = require('fs');
process.chdir('recipes'); // 改變工作目錄
var concatenation = '';

fs.readdir('.', function(err, filenames) {
  if (err) throw err;

  function readFileAt(i) {
    var filename = filenames[i];
    fs.stat(filename, function(err, stats) {
      if (err) throw err;
      if (! stats.isFile()) return readFileAt(i + 1);

      fs.readFile(filename, 'utf8', function(err, text) {
        if (err) throw err;
        concatenation += text;
        if (i + 1 === filenames.length) {
          // 所有文件均已讀取,可顯示輸出
          return console.log(concatenation);
        }
        readFileAt(i + 1);
      });
    });
  }
  readFileAt(0);
});

如你所見(jiàn),異步版本的代碼要比同步版本多很多。如果使用filter、forEach這些同步方法,代碼的行數(shù)大約只有一半,而且讀起來(lái)也要容易得多。如果這些漂亮的迭代器存在異步版本該多好??!使用Async.js就能做到這一點(diǎn)!

 

何時(shí)拋出亦無(wú)妨?

大家可能注意到了,在上面那個(gè)代碼示例中筆者無(wú)視了自己在第1.4節(jié)中提出的建議:從回調(diào)里拋出異常是一種糟糕的設(shè)計(jì),尤其在成品環(huán)境中。不過(guò),一個(gè)簡(jiǎn)單如斯的示例直接拋出異常則完全沒(méi)有問(wèn)題。如果真的遇到代碼出錯(cuò)的意外情形,throw會(huì)關(guān)停代碼并提供一個(gè)漂亮的堆棧軌跡來(lái)解釋出錯(cuò)原因。

這里真正的不妥之處在于,同樣的錯(cuò)誤處理邏輯(即if(err) throw err)重復(fù)了多達(dá)3次!在4.2.2節(jié),我們會(huì)看到Async.js如何幫助減少這種重復(fù)。

Async.js的函數(shù)式寫(xiě)法
我們想把同步迭代器所使用的filter和forEach方法替換成相應(yīng)的異步方法。Async.js給了我們兩個(gè)選擇。

async.filter和async.forEach,它們會(huì)并行處理給定的數(shù)組。
async.filterSeries和async.forEachSeries,它們會(huì)順序處理給定的數(shù)組。
并行運(yùn)行這些異步操作應(yīng)該會(huì)更快,那為什么還要使用序列式方法呢?原因有兩個(gè)。

前面提到的工作流次序不可預(yù)知的問(wèn)題。我們確實(shí)可以先把結(jié)果存儲(chǔ)成數(shù)組,然后再joining(聯(lián)接)數(shù)組來(lái)解決這個(gè)問(wèn)題,但這畢竟多了一個(gè)步驟。
Node及其他任何應(yīng)用進(jìn)程能夠同時(shí)讀取的文件數(shù)量有一個(gè)上限。如果超過(guò)這個(gè)上限,操作系統(tǒng)就會(huì)報(bào)錯(cuò)。如果能順序讀取文件,則無(wú)需擔(dān)心這一限制。
所以現(xiàn)在先搞明白async.forEachSeries再說(shuō)。下面使用了Async.js的數(shù)據(jù)收集方法,直接改寫(xiě)了同步版本的代碼實(shí)現(xiàn)。

Asyncjs/forEachSeries.js

復(fù)制代碼 代碼如下:

var async = require('async');
var fs = require('fs');
process.chdir('recipes'); // 改變工作目錄
var concatenation = '';

var dirContents = fs.readdirSync('.');

async.filter(dirContents, isFilename, function(filenames) {
  async.forEachSeries(filenames, readAndConcat, onComplete);
});

function isFilename(filename, callback) {
  fs.stat(filename, function(err, stats) {
    if (err) throw err;
    callback(stats.isFile());
  });
}

function readAndConcat(filename, callback) {
  fs.readFile(filename, 'utf8', function(err, fileContents) {
    if (err) return callback(err);
    concatenation += fileContents;
    callback();
  });
}

function onComplete(err) {
  if (err) throw err;
  console.log(concatenation);
}

現(xiàn)在我們的代碼漂亮地分成了兩個(gè)部分:任務(wù)概貌(表現(xiàn)形式為async.filter調(diào)用和async.forEachSeries調(diào)用)和實(shí)現(xiàn)細(xì)節(jié)(表現(xiàn)形式為兩個(gè)迭代器函數(shù)和一個(gè)完工回調(diào)onComplete)。

filter和forEach并不是僅有的與標(biāo)準(zhǔn)函數(shù)式迭代方法相對(duì)應(yīng)的Async.js工具函數(shù)。Async.js還提供了以下方法:

reject/rejectSeries,與filter剛好相反;
map/mapSeries,1:1變換;
reduce/reduceRight,值的逐步變換;
detect/detectSeries,找到篩選器匹配的值;
sortBy,產(chǎn)生一個(gè)有序副本;
some,測(cè)試是否至少有一個(gè)值符合給定標(biāo)準(zhǔn);
every,測(cè)試是否所有值均符合給定標(biāo)準(zhǔn)。
這些方法是Async.js的精髓,令你能夠以最低的代碼重復(fù)度來(lái)執(zhí)行常見(jiàn)的迭代工作。在繼續(xù)探索更高級(jí)的方法之前,我們先來(lái)看看這些方法的錯(cuò)誤處理技術(shù)。

Async.js的錯(cuò)誤處理技術(shù)
要怪就怪Node的fs.exists首開(kāi)這一先河吧!而這也意味著使用了Async.js數(shù)據(jù)收集方法(filter/filterSeries、reject/rejectSeries、detect/detectSeries、some、every等)的迭代器均無(wú)法報(bào)告錯(cuò)誤。

對(duì)于非布爾型的所有Async.js迭代器,傳遞非null/undefined的值作為迭代器回調(diào)的首參數(shù)將會(huì)立即因該錯(cuò)誤值而調(diào)用完工回調(diào)。這正是readAndConcat不用throw也能工作的原因。

Asyncjs/forEachSeries.js

復(fù)制代碼 代碼如下:

function readAndConcat(filename, callback) {
  fs.readFile(filename, 'utf8', function(err, fileContents) {
    if (err) return callback(err);
    concatenation += fileContents;
    callback();
  });
}

所以,如果callback(err)確實(shí)是在readAndConcat中被調(diào)用的,則這個(gè)err會(huì)傳遞給完工回調(diào)(即onComplete)。Async.js只負(fù)責(zé)保證onComplete只被調(diào)用一次,而不管是因首次出錯(cuò)而調(diào)用,還是因成功完成所有操作而調(diào)用。

Asyncjs/forEachSeries.js

復(fù)制代碼 代碼如下:

function onComplete(err) {
  if (err) throw err;
  console.log(concatenation);
}

Node的錯(cuò)誤處理約定對(duì)Async.js數(shù)據(jù)收集方法而言也許并不理想,但對(duì)于Async.js的所有其他方法而言,遵守這些約定可以讓錯(cuò)誤干凈利落地從各個(gè)任務(wù)流向完工回調(diào)。下一節(jié)會(huì)看到更多這樣的例子。

相關(guān)文章

  • 詳解Javascript?基于長(zhǎng)連接的服務(wù)框架問(wèn)題

    詳解Javascript?基于長(zhǎng)連接的服務(wù)框架問(wèn)題

    本文針對(duì)經(jīng)常使用長(zhǎng)連接進(jìn)行消息收發(fā)的應(yīng)答場(chǎng)景,采用 Websocket 長(zhǎng)連接作為服務(wù)監(jiān)聽(tīng)的對(duì)象,模擬了一套類 http 服務(wù)框架,通過(guò)實(shí)例代碼介紹了Javascript?基于長(zhǎng)連接的服務(wù)框架,需要的朋友可以參考下
    2022-07-07
  • Bootstrap CSS布局之列表

    Bootstrap CSS布局之列表

    這篇文章主要為大家詳細(xì)介紹了Bootstrap CSS布局之列表的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 小程序清理本地緩存的方法

    小程序清理本地緩存的方法

    這篇文章主要介紹了小程序清理本地緩存的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • JavaScript中的類型判斷你真的了解了嗎

    JavaScript中的類型判斷你真的了解了嗎

    這篇文章主要為大家詳細(xì)介紹了JavaScript中類型判斷的相關(guān)常見(jiàn)方法,文中的示例代碼講解詳細(xì),對(duì)我們深入學(xué)習(xí)JavaScript有一定幫助,需要的可以參考下
    2023-11-11
  • Javascript中的匿名函數(shù)與封裝介紹

    Javascript中的匿名函數(shù)與封裝介紹

    這篇文章主要介紹了Javascript中的匿名函數(shù)與封裝介紹,本文分析了jQuery 封裝、Backbone 封裝、Underscore 封裝等內(nèi)容,需要的朋友可以參考下
    2015-03-03
  • 詳解cordova打包成webapp的方法

    詳解cordova打包成webapp的方法

    本篇文章主要介紹了詳解cordova打包成webapp的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • js阻止默認(rèn)右鍵的下拉菜單方法

    js阻止默認(rèn)右鍵的下拉菜單方法

    下面小編就為大家分享一篇js阻止默認(rèn)右鍵的下拉菜單方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • 基于JS繪制2021的煙花效果 附源碼下載

    基于JS繪制2021的煙花效果 附源碼下載

    這篇文章主要介紹了基于JS繪制2021的煙花效果,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • 利用HTML5的畫(huà)布Canvas實(shí)現(xiàn)刮刮卡效果

    利用HTML5的畫(huà)布Canvas實(shí)現(xiàn)刮刮卡效果

    大家都玩過(guò)刮刮樂(lè)吧,都想一夜暴富,本文給大家分享一款利用HTML5的畫(huà)布Canvas實(shí)現(xiàn)刮刮卡效果,需要的朋友可以參考下
    2015-09-09
  • js實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)重定向的幾種方式

    js實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)重定向的幾種方式

    這篇文章主要介紹js實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)重定向的幾種方式,需要的朋友可以參考下
    2014-05-05

最新評(píng)論