欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入淺析NodeJs并發(fā)異步的回調(diào)處理

 更新時(shí)間:2015年12月21日 09:29:47   作者:onlyfu  
這篇文章主要介紹了NodeJs并發(fā)異步的回調(diào)處理的相關(guān)資料,需要的朋友可以參考下

這里說并發(fā)異步,并不準(zhǔn)確,應(yīng)該說連續(xù)異步。NodeJs單線程異步的特性,直接導(dǎo)致多個(gè)異步同時(shí)進(jìn)行時(shí),無法確定最后的執(zhí)行結(jié)果來回調(diào)。舉個(gè)簡單的例子:

for(var i = 0; i < 5; i++) {
  fs.readFile('file', 'utf-8', function(error, data){});
} 

連續(xù)發(fā)起了5次讀文件的異步操作,很簡單,那么問題來了,我怎么確定所有異步都執(zhí)行完了呢?因?yàn)橐谒鼈兌紙?zhí)行完后,才能進(jìn)行之后的操作。相信有點(diǎn)經(jīng)驗(yàn)的同學(xué)都會想到使用記數(shù)的方式來進(jìn)行,但如何保證記數(shù)正確又是一個(gè)問題。仔細(xì)想想:

回調(diào)是一個(gè)函數(shù),每個(gè)異步操作時(shí)將計(jì)數(shù)器+1,當(dāng)每個(gè)異步結(jié)束時(shí)將計(jì)數(shù)器-1,通過判斷計(jì)數(shù)器是否為0來確定是否執(zhí)行回調(diào)。這個(gè)邏輯很簡單,需要一個(gè)相對于執(zhí)行時(shí)和回調(diào)時(shí)的全局變量作為計(jì)數(shù)器,而且要在傳給異步方法是執(zhí)行+1的操作,而且之后將返回一個(gè)用來回調(diào)的函數(shù),有點(diǎn)繞,不過看看Js函數(shù)的高級用法:

var pending = (function() {
  var count = 0;
  return function() {
    count++;
    return function() {
      count--;
      if (count === 0) {
        // 全部執(zhí)行完畢
      }
    }
  }
}); 

當(dāng)pending調(diào)用時(shí),即pending(),比如:

var done = pending(); 

這時(shí)計(jì)數(shù)變量count即被初始化為0,返回的函數(shù)附給了done,這時(shí)如果執(zhí)行done(),會是什么?是不是直接執(zhí)行pending返回的第一個(gè)函數(shù),即:pending()(),這個(gè)執(zhí)行又是什么,首先將計(jì)數(shù)變量count+1,又返回了一個(gè)函數(shù),這個(gè)函數(shù)直接當(dāng)做callback傳給異步的方法,當(dāng)執(zhí)行這個(gè)callback的時(shí)候,首先是將計(jì)數(shù)變量count-1,再判斷count是否為0,如果為0即表示所有的異步執(zhí)行完成了,從而達(dá)到連續(xù)的異步,同一回調(diào)的操作。

關(guān)鍵就在兩個(gè)return上,簡單的說:

第一個(gè)return的函數(shù)是將count+1,接著返回需要回調(diào)的函數(shù)

第二個(gè)return的函數(shù)就是需要回調(diào)的函數(shù),如果它執(zhí)行,就是將count-1,然后判斷異步是否全部執(zhí)行完成,完成了,就回調(diào)

看個(gè)實(shí)際點(diǎn)的例子,讀取多個(gè)文件的異步回調(diào):

var fileName = ['1.html', '2.html', '3.html'];
var done = pending(function(fileData) {
  console.log('done');
  console.log(fielData);
});
for(var i = 0; i < fileName.lenght; i++) {
  fs.readFile(fileName[i], 'utf-8', done(fileName[i]));
}

其中的done,即用pending方法包起了我們想回調(diào)執(zhí)行的方法,當(dāng)計(jì)數(shù)器為0時(shí),就會執(zhí)行它,那我們得改進(jìn)一下pending方法:

var pending = (function(callback) {
  var count = 0;
  var returns = {};
  console.log(count);
  return function(key) {
    count++;
    console.log(count);
    return function(error, data) {
      count--;
      console.log(count);
      returns[key] = data;
      if (count === 0) {
        callback(returns);
      }
    }
  }
}); 

callback即為我們的回調(diào)函數(shù),當(dāng)var done = pending(callback)時(shí),done其實(shí)已為第一個(gè)return的函數(shù),它有一個(gè)參數(shù),可以當(dāng)做返回的值的下標(biāo),所以在循環(huán)體中done(fileName[i]),把文件名傳了進(jìn)去。這個(gè)done()是直接執(zhí)行的,它將count+1后,返回了要傳給異步方法的回調(diào)函數(shù),如前面所說,這個(gè)回調(diào)函數(shù)里會根據(jù)計(jì)數(shù)變量來判斷是否執(zhí)行我們希望執(zhí)行的回調(diào)函數(shù),而且把文件的內(nèi)容傳給了它,即returns。好了,運(yùn)行一下,相信能夠準(zhǔn)確的看到運(yùn)行結(jié)果。

0
1
2
3
2
1
0
done
{"1.html": "xxx", "2.html": "xxx", "3.html": "xxx"}

從計(jì)數(shù)上明顯能看出,從0-3再到0,之后就是我們的回調(diào)函數(shù)輸出了done和文件的內(nèi)容。

這個(gè)問題解決了,我們要思考一下,如何讓這樣的方法封裝重用,不然,每次都寫pending不是很不科學(xué)嗎?

下面看看UnJs(我的一個(gè)基于NodeJs的Web開發(fā)框架)的處理方式,應(yīng)用于模板解析中的子模板操作:

unjs.asyncSeries = function(task, func, callback) {
  var taskLen = task.length;
  if (taskLen <= 0) {
    return;
  }
  var done = unjs.pending(callback);
  for(var i = 0; i < taskLen; i++) {
    func(task[i], done);
  }
} 

asyncSeries有三個(gè)參數(shù),意思是:

task: 需要處理的對象,比如需要讀取的文件,它是一個(gè)列表,如果不是列表,或列表長度為0,它將不會執(zhí)行

func: 異步方法,比如fs.readFile,就是通過它傳進(jìn)去的

callback: 我們希望回調(diào)的方法

done和前面同理,它傳給了func,但并沒有執(zhí)行,因?yàn)橄M麘?yīng)用端能可控制參數(shù),所以讓應(yīng)用端去執(zhí)行。

再看看處理子模板時(shí)的操作:

var subTemplate = [];
var patt = /\{\% include \'(.+)\' \%\}/ig;
while(sub = patt.exec(data)) {
  var subs = sub;
  subTemplate.push([subs[0], subs[1]]);
}
unjs.asyncSeries(subTemplate, function(item, callback) {
  fs.readFile('./template/' + item[1], 'utf-8', callback(item[0]));
}, function(data) {
  for(var key in data) {
    html = html.replace(key, data[key]);
  }
}); 

subTemplate這個(gè)列表,是根據(jù)對子模板的解析生成的數(shù)據(jù),它是一個(gè)二維的數(shù)組,每個(gè)子項(xiàng)的第一個(gè)值為子模板的調(diào)用文本,即:{% include 'header.html' %}這樣的字符串,第二個(gè)參數(shù)為子模板文件名,即:header.html

asyncSeries的第二個(gè)參數(shù)是的callback,實(shí)際上是第三個(gè)參數(shù),也就是我們希望執(zhí)行的回調(diào)函數(shù)經(jīng)過pending處理的回調(diào)方法,如前面所說,在asyncSeries內(nèi)部,它并沒有運(yùn)行,而是到這里運(yùn)行的,即:callback(item[0]),帶上了參數(shù),因?yàn)楹竺孢€要根據(jù)這個(gè)參數(shù)將父模板中調(diào)用子模板的字符串替換為對應(yīng)子模板的內(nèi)容。

這樣子,只要需要連續(xù)異步時(shí),就可以使用asyncSeries方法來處理了。因?yàn)楫惒降年P(guān)系,程序的流程有點(diǎn)繞,可能開始不太好理解,即使熟悉了,也有可能突然想不明白,沒關(guān)系,比如,第二個(gè)參數(shù)中的callback實(shí)際是第三個(gè)參數(shù)生成的,開始可能你就會想,這個(gè)callback倒底是啥。還有就是pending的兩個(gè)return,也是不太好理解的,需要多想想。

好了,連續(xù)異步的回調(diào)使用Js函數(shù)的高級特性完成了。但NodeJs的異步性著實(shí)讓程序的控制很成問題,諸如還有連續(xù)異步,但要傳值的操作等,這些都是可以通過這樣的思路,變化一下即可實(shí)現(xiàn)的。

以上內(nèi)容是小編給大家分享的NodeJs并發(fā)異步的回調(diào)處理的相關(guān)知識,希望大家喜歡。

相關(guān)文章

  • node.js中的http.createServer方法使用說明

    node.js中的http.createServer方法使用說明

    這篇文章主要介紹了node.js中的http.createServer方法使用說明,本文介紹了http.createServer的方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • Node.js卸載與重裝及zip與msi安裝詳解

    Node.js卸載與重裝及zip與msi安裝詳解

    Node.js是一個(gè)JavaScript運(yùn)行環(huán)境,可以使JavaScript這類腳本語言編寫出來的代碼運(yùn)行速度獲得極大提升,下面這篇文章主要給大家介紹了關(guān)于Node.js卸載與重裝及zip與msi安裝的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • 使用pkg打包nodejs項(xiàng)目并解決本地文件讀取的問題

    使用pkg打包nodejs項(xiàng)目并解決本地文件讀取的問題

    這篇文章主要介紹了使用pkg打包nodejs項(xiàng)目并解決本地文件讀取的問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • 淺談Node.js CVE-2017-14849 漏洞分析(詳細(xì)步驟)

    淺談Node.js CVE-2017-14849 漏洞分析(詳細(xì)步驟)

    這篇文章主要介紹了淺談Node.js CVE-2017-14849 漏洞分析(詳細(xì)步驟),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • node連接MySQL數(shù)據(jù)庫的3種方式總結(jié)

    node連接MySQL數(shù)據(jù)庫的3種方式總結(jié)

    現(xiàn)在前端基本上都會用一些NodeJs,想必也想自己寫一些API或者個(gè)人博客的后臺系統(tǒng),這些就離不開連接數(shù)據(jù)庫的問題,下面這篇文章主要給大家介紹了關(guān)于node連接MySQL數(shù)據(jù)庫的3種方式,需要的朋友可以參考下
    2022-08-08
  • 淺析 NodeJs 的幾種文件路徑

    淺析 NodeJs 的幾種文件路徑

    本篇文章主要介紹了淺析 NodeJs 的幾種文件路徑,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • 在Linux系統(tǒng)中搭建Node.js開發(fā)環(huán)境的簡單步驟講解

    在Linux系統(tǒng)中搭建Node.js開發(fā)環(huán)境的簡單步驟講解

    這篇文章主要介紹了在Linux系統(tǒng)中搭建Node.js開發(fā)環(huán)境的步驟,Node使得JavaScript程序可以在本地操作系統(tǒng)環(huán)境中解釋運(yùn)行,需要的朋友可以參考下
    2016-01-01
  • Yarn的安裝與使用詳細(xì)介紹

    Yarn的安裝與使用詳細(xì)介紹

    不知道大家有沒有覺察到Facebook近年大招頻出。Yarn是Facebook最近發(fā)布的一款依賴包安裝工具。Yarn是一個(gè)新的快速安全可信賴的可以替代NPM的依賴管理工具,Yarn正式發(fā)布沒幾天已經(jīng)迅速達(dá)到了數(shù)萬贊,就可以知道大家苦NPM久已。這篇文章將詳細(xì)介紹Yarn的安裝與使用。
    2016-10-10
  • node.js中的fs.truncateSync方法使用說明

    node.js中的fs.truncateSync方法使用說明

    這篇文章主要介紹了node.js中的fs.truncateSync方法使用說明,本文介紹了fs.truncateSync的方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • Node express 官方示例cors跨域解析

    Node express 官方示例cors跨域解析

    這篇文章主要為大家介紹了Node express 官方示例cors跨域解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08

最新評論