最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Nodejs 數(shù)組的隊(duì)列以及forEach的應(yīng)用詳解

 更新時(shí)間:2021年02月25日 16:01:26   作者:WificamSDK7  
這篇文章主要介紹了Nodejs 數(shù)組的隊(duì)列以及forEach的應(yīng)用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧

本文主要記錄了在Nodejs開發(fā)過程中遇到過的由數(shù)組特性引起的問題及解決方式,以及對(duì)數(shù)組的靈活應(yīng)用。

本文代碼測(cè)試結(jié)果均基于node v6.9.5

數(shù)組與隊(duì)列

利用數(shù)組對(duì)象方法push/shift可實(shí)現(xiàn)隊(duì)列先進(jìn)先出特性,例如:

>a=[]
[]
>a.push(2.3.4)
3
>a.push(2)
3
>a
[2.3.4.2]
>a.shift()
2
>a
>[3.4.2]

數(shù)組與forEach

對(duì)數(shù)組的刪除操作有兩種常見方式:delete和使用splice方法,需要明確他們的區(qū)別。

操作/方法 說(shuō)明
splice 刪除并返回指定的數(shù)組元素,數(shù)組本身長(zhǎng)度會(huì)改變;但不會(huì)free元素對(duì)象
delete 刪除(free)元素對(duì)象,數(shù)組元素不變,值變?yōu)閡ndefined

如果要從數(shù)組中徹底刪除某個(gè)元素,使用splice即可:

> a=[1,2,3]
[ 1, 2, 3 ]
> a.splice(1,1)
[ 2 ]
> a
[ 1, 3 ]
> a.length
2
> a.forEach(function(item, index){console.info("index[", index,"]:", item)});
index[ 0 ]: 1
index[ 1 ]: 3
undefined
> 

那么,當(dāng)使用delete刪除某個(gè)元素對(duì)象后,此時(shí)執(zhí)行forEach的效果是什么?

forEach對(duì)含空元素?cái)?shù)組處理機(jī)制

測(cè)試結(jié)果如下

> a=[1,2,3]
[ 1, 2, 3 ]
> delete a[1]
true
> a
[ 1, , 3 ]
> a.length
3
> a.forEach(function(item, index){console.info("index[", index,"]:", item)});
index[ 0 ]: 1
index[ 2 ]: 3
undefined

從測(cè)試結(jié)果來(lái)看,forEach并不會(huì)遍歷到值為undefined的哪一項(xiàng)。這在實(shí)際應(yīng)用中如何判斷forEach是否結(jié)束是一大挑戰(zhàn)。

解決配合forEach的異步特性應(yīng)用,可為數(shù)組添加prototype來(lái)自行管理設(shè)置有效數(shù)據(jù);

效果如下:

> a=[1,2,3]
[ 1, 2, 3 ]
> a.validnum=3
3
> delete a[2]
true
> a.validnum=2
2
> a
[ 1, 2, , validnum: 2 ]
> a.length
3
> a.validnum
2
> a.forEach(function(item, index){console.info("index[", index,"]:", item)});
index[ 0 ]: 1
index[ 1 ]: 2
undefined
> 

補(bǔ)充:Node.js 數(shù)組 forEach 同步處理上下文語(yǔ)句

習(xí)慣了C語(yǔ)言系的思維方式,剛接觸Node.js,它的異步處理讓我頭大。

寫代碼遇到這么一個(gè)場(chǎng)景,需要循環(huán)對(duì)一個(gè)數(shù)組中的元素進(jìn)行處理,全部處理完成后再執(zhí)行一個(gè)last操作。但是JS的異步特性會(huì)使這個(gè)last語(yǔ)句先執(zhí)行,所以花點(diǎn)時(shí)間研究研究forEach。

Talk is cheap. Show me the code.

forEach 用法

forEach用于對(duì)數(shù)組結(jié)構(gòu)進(jìn)行遍歷,看到有人說(shuō)forEach底層是用for實(shí)現(xiàn)的,沒深究,起碼效果上看是一樣的。forEach的回調(diào)函數(shù)3個(gè)參數(shù)分別是:值、序號(hào)和原數(shù)組。序號(hào)從0開始。

(() => {
  let arr = [2, 3, 1];
  arr.forEach(function (value, index, array) {
    console.log(value);
    console.log(index);
    console.log(array);
    console.log('-----');
  });
})();

Output

2
0
[ 2, 3, 1 ]
-----
3
1
[ 2, 3, 1 ]
-----
1
2
[ 2, 3, 1 ]
-----

從結(jié)果上看forEach多次循環(huán)之間是同步的,也就是說(shuō)都是按順序執(zhí)行的。但是一想到它是JS就感覺不可能同步的。??梢则?yàn)證一下。

forEach 異步處理多次循環(huán)

這次在forEach加個(gè)定時(shí)任務(wù),每次循環(huán)操作都延時(shí)value相關(guān)的時(shí)間,模擬比較耗時(shí)的操作。

(() => {
  let arr = [2, 3, 1];
  arr.forEach(function (value, index, array) {
    setTimeout(function () {
      console.log(value);
    }, value*100);
  });
})();

Output

1
2
3

從結(jié)果可以看出耗時(shí)最短的任務(wù)先完成,每次循環(huán)的任務(wù)并不是按循環(huán)的先后順序執(zhí)行的,也就是說(shuō)異步處理多次循環(huán)。

forEach 上下文也是異步執(zhí)行

回到開始說(shuō)到的問題了,且不管多次循環(huán)是不是按順序執(zhí)行,我需要forEach中的所有任務(wù)都完成后執(zhí)行一條數(shù)據(jù)來(lái)通知我任務(wù)全部完成了。

(() => {
  let arr = [2, 3, 1];
  arr.forEach(function (value, index, array) {
    setTimeout(function () {
      console.log(value);
    }, value*100);
  });
  console.log('All the work is done');
})();

Output

All the work is done
1
2
3

從結(jié)果來(lái)看,上下文的語(yǔ)句也不是同步的,forEach循環(huán)中的任務(wù)沒有完成就通知所有任務(wù)都完成了,顯然不符合預(yù)期。

針對(duì)這個(gè)問題看了好多個(gè)博客,都沒有找到合適的解決方法,最后只能想到用Promise.all來(lái)勉強(qiáng)實(shí)現(xiàn)這個(gè)功能。

Promise.all 實(shí)現(xiàn) forEach 上下文語(yǔ)句同步處理

把上面的代碼改成Promise.all的結(jié)構(gòu)。每個(gè)循環(huán)中執(zhí)行結(jié)束調(diào)用resolve(),我們知道Promise.all的then函數(shù),只有所有的Promise都執(zhí)行完成才會(huì)觸發(fā),這樣好像能滿足我們的需求。

(() => {
  let arr = [2, 3, 1];
  let proArr = [];
  arr.forEach(function (value, index) {
    proArr[index] = new Promise(function (resolve) {
      setTimeout(function () {
        console.log(value);
        resolve();
      }, value*100);
    });
  });
  Promise.all(proArr).then(()=>{
    console.log('All the work is done');
  })
})();

Output

1
2
3
All the work is done

從結(jié)果來(lái)看,滿足了我們的需求。

可能還存在的問題

想到JS異步特性,突然發(fā)現(xiàn)可能這個(gè)方法還存在個(gè)問題。

這里每次 forEach 剛進(jìn)入就對(duì) Promise 數(shù)組進(jìn)行了賦值操作,這個(gè)操作時(shí)間應(yīng)該非常短,循環(huán)3次都賦值完成后才調(diào)用最后的Promise.all語(yǔ)句。

但是如果這個(gè)數(shù)組非常大,這個(gè)循環(huán)賦值的操作非常耗時(shí)間的話,假如只完成了一半的賦值操作,那么執(zhí)行最后這個(gè) Promise.all 的時(shí)候傳入的 Promise 數(shù)組可能并不是包含所有 Promise 的數(shù)組。

這樣的話 Promise.all 等待的就只有一半的操作,Promise.all 等待的時(shí)候,這個(gè)數(shù)組后面被賦值的 Promise 不知道會(huì)不會(huì)被等待。

剛接觸JS不明白實(shí)現(xiàn)機(jī)制,只能實(shí)驗(yàn)來(lái)驗(yàn)證一下是否存在這個(gè)問題。接下來(lái)用把這個(gè)數(shù)組弄大一些,請(qǐng)?jiān)徫矣米钌倒鲜降姆绞礁愦笏?/p>

(() => {
  let arr = [2, 3, 1, 2, 3, 1, 2, 3, 1, 2];  // 10
  arr= arr.concat(arr);  // 2^1 * 10
  arr= arr.concat(arr);  // 2^2 * 10
  arr= arr.concat(arr);  // 2^3
  arr= arr.concat(arr);  // 2^4
  arr= arr.concat(arr);  // 2^5
  arr= arr.concat(arr);
  arr= arr.concat(arr);
  arr= arr.concat(arr);
  arr= arr.concat(arr);
  arr= arr.concat(arr);  // 2^10
  arr= arr.concat(arr);
  arr= arr.concat(arr);
  arr= arr.concat(arr);
  arr= arr.concat(arr);
  arr= arr.concat(arr);  // 2^15
  arr= arr.concat(arr);
  arr= arr.concat(arr); // 2^17 * 10
// arr= arr.concat(arr);  // 2^18 * 10
  console.log(arr.length);
  let proArr = [];
  arr.forEach(function (value, index) {
    proArr[index] = new Promise(function (resolve) {
      setTimeout(function () {
        console.log(value);
        resolve();
      }, value*100);
    });
  });
  Promise.all(proArr).then(()=>{
    console.log('All the work is done');
    console.log(arr.length);
  }).catch(function (err) {
    console.log(err);
  })
})();

經(jīng)過測(cè)試在我這個(gè)電腦上當(dāng)數(shù)組長(zhǎng)度為2^18 * 10的時(shí)候,Promise報(bào)錯(cuò) RangeError: Too many elements passed to Promise.all。

當(dāng)數(shù)組長(zhǎng)度為2^17 * 10 即2621440的時(shí)候,會(huì)正常運(yùn)行。測(cè)試了幾次,最后的執(zhí)行命令輸出的All the work is done始終在最后輸出(因?yàn)榻K端緩沖區(qū)太小,所以使用node xx.js > log.txt重定向的方式把輸出結(jié)果重定向到文件查看)。

當(dāng)然應(yīng)用中也不會(huì)有這么大的數(shù)組,從結(jié)果看的話,就是實(shí)際應(yīng)用中不存在上面考慮可能出現(xiàn)的問題。

也就是說(shuō)可以用 Promise.all 實(shí)現(xiàn) forEach 上下文語(yǔ)句同步處理。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • node-sass@4.14.1報(bào)錯(cuò)的最終解決方案分享

    node-sass@4.14.1報(bào)錯(cuò)的最終解決方案分享

    最近在安裝node-sass@4.14.1的時(shí)候遇到了些問題,所以下面這篇文章主要給大家介紹了關(guān)于node-sass@4.14.1報(bào)錯(cuò)的最終解決方案,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • Node.js Koa2使用JWT進(jìn)行鑒權(quán)的方法示例

    Node.js Koa2使用JWT進(jìn)行鑒權(quán)的方法示例

    這篇文章主要介紹了Node.js Koa2使用JWT進(jìn)行鑒權(quán)的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2018-08-08
  • node.js中的fs.readdirSync方法使用說(shuō)明

    node.js中的fs.readdirSync方法使用說(shuō)明

    這篇文章主要介紹了node.js中的fs.readdirSync方法使用說(shuō)明,本文介紹了fs.readdirSync方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • Express下采用bcryptjs進(jìn)行密碼加密的方法

    Express下采用bcryptjs進(jìn)行密碼加密的方法

    本篇文章主要介紹了Express下采用bcryptjs進(jìn)行密碼加密的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2018-02-02
  • node.js利用socket.io實(shí)現(xiàn)多人在線匹配聯(lián)機(jī)五子棋

    node.js利用socket.io實(shí)現(xiàn)多人在線匹配聯(lián)機(jī)五子棋

    這篇文章主要介紹了node.js利用socket.io實(shí)現(xiàn)多人在線匹配聯(lián)機(jī)五子棋的操作方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-05-05
  • node.js中的http.get方法使用說(shuō)明

    node.js中的http.get方法使用說(shuō)明

    這篇文章主要介紹了node.js中的http.get方法使用說(shuō)明,本文介紹了http.get的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • nodejs遞歸文件夾獲取所有文件路徑實(shí)例

    nodejs遞歸文件夾獲取所有文件路徑實(shí)例

    這篇文章主要為大家介紹了nodejs遞歸文件夾獲取所有文件路徑實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Node.js學(xué)習(xí)之查詢字符串解析querystring詳解

    Node.js學(xué)習(xí)之查詢字符串解析querystring詳解

    這篇文章主要給大家介紹了關(guān)于Node.js查詢字符串解析querystring的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用node.js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-09-09
  • node 利用進(jìn)程通信實(shí)現(xiàn)Cluster共享內(nèi)存

    node 利用進(jìn)程通信實(shí)現(xiàn)Cluster共享內(nèi)存

    本篇文章主要介紹了node 利用進(jìn)程通信實(shí)現(xiàn)Cluster共享內(nèi)存,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2017-10-10
  • 使用iojs的jsdom庫(kù)實(shí)現(xiàn)同步系統(tǒng)時(shí)間

    使用iojs的jsdom庫(kù)實(shí)現(xiàn)同步系統(tǒng)時(shí)間

    本文給大家分享的是使用iojs的jsdom庫(kù)實(shí)現(xiàn)與http://open.baidu.com/special/time/ 同步系統(tǒng)時(shí)間。思路非常的清晰,這里推薦給大家,有需要的小伙伴可以參考下。
    2015-04-04

最新評(píng)論

天等县| 体育| 张掖市| 仙游县| 万安县| 来安县| 长丰县| 元江| 桓仁| 大名县| 大余县| 张家港市| 兖州市| 台中市| 建瓯市| 汕尾市| 泾阳县| 临江市| 隆昌县| 大城县| 博湖县| 卓资县| 綦江县| 沾化县| 镇沅| 湟中县| 清新县| 句容市| 凤凰县| 东丽区| 霍城县| 大邑县| 游戏| 富川| 安塞县| 兴城市| 吉安县| 拉萨市| 巧家县| 东乡族自治县| 孝昌县|