欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

JS異步任務(wù)的并行、串行,以及二者結(jié)合

freeflydom
2023年10月27日 17:41 本文熱度 616

讓多個(gè)異步任務(wù)按照我們的想法執(zhí)行,是開發(fā)中常見的需求。今天我們就來捋一下,如何讓多個(gè)異步任務(wù)并行,串行,以及并行串行相結(jié)合。

 

一、并行

并行是使用最多的方式,多個(gè)相互間沒有依賴關(guān)系的異步任務(wù),并行執(zhí)行能夠提高效率。

我們最經(jīng)常用的,是Promise.all() 。


function f1() {    
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('1結(jié)束');
            resolve();
        }, 1000)
    });
}
function f2() {    
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('2結(jié)束');
            resolve();
        }, 900)
    });
}
function f3() {    
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('3結(jié)束');
            resolve();
        }, 800)
    });
}
let arr = [f1, f2, f3];
Promise.all(arr.map(i => i()));// 3結(jié)束// 2結(jié)束// 1結(jié)束

以下幾種數(shù)組遍歷方式,同樣可以實(shí)現(xiàn)并行。


arr.forEach(item => (let i = 0; i < arr.length; i++arr.forEach(async item =>=>

相比之下,Promise.all()可以確保任務(wù)都執(zhí)行成功,然后再執(zhí)行后續(xù)操作,這是各種遍歷無法做到的。

另外,還有一種方式也能實(shí)現(xiàn)并行:Promise.allSettled()。

Promise.allSettled(arr.map(i => i()));

這種方式很特別,它無法得到每個(gè)Promise對(duì)象的返回值,卻可以精確得知每個(gè)任務(wù)的成功還是失敗。如果你有這樣的需求場(chǎng)景,用Promise.allSettled()就很合適。

 

二、串行

我在工作中遇到過一個(gè)場(chǎng)景,一個(gè)有1000+元素的數(shù)組,每個(gè)成員都是調(diào)用第三方接口的Promise對(duì)象。我像往常一樣得意的使用Promise.all(),等著1000多個(gè)任務(wù)瞬間完成。然而,結(jié)果卻讓我大跌眼鏡,這1000多個(gè)任務(wù),只有一部分成功了,大部分都報(bào)錯(cuò)了。不管我執(zhí)行幾次,結(jié)果都是這個(gè)樣。一籌莫展之后,我才從第三方那兒得知,他們的接口是有調(diào)用限制的,一個(gè)接口同一時(shí)間只能并行300個(gè)。

有沒有辦法能讓它們一個(gè)接一個(gè)的執(zhí)行呢?也就是串行。

nodejs koa框架的next()語法給了我啟發(fā),它就是讓中間件一個(gè)接一個(gè)的執(zhí)行。于是我想出了遞歸的方式:


async function serial(arr) {
    let item = arr.shift();
    await item();    
    if (arr.length > 0) {
        await serial(arr);
    }
}
serial(arr);// 1結(jié)束// 2結(jié)束// 3結(jié)束

其實(shí),想讓異步任務(wù)串行,不用這么麻煩。以下遍歷的方式,同樣可以實(shí)現(xiàn)串行。


// 使用for...of
async function f() {    
    for (let item of arr) {
        await item();
    }
}
f();// 使用for循環(huán)
async function f() {    
    for (let i = 0; i < arr.length; i++) {
        await arr[i]();
    }
}
f();

發(fā)現(xiàn)了沒?為什么同樣是for循環(huán),同樣是for...of,前面的寫法是并行,后面就成了串行呢?

工作中,我們一定做過這樣的嘗試,想通過遍歷,來讓多個(gè)異步任務(wù)串行。但往往不得其法,怎么折騰它們都還是同時(shí)執(zhí)行。

后一種寫法,你可以理解為:await執(zhí)行完成后,才會(huì)進(jìn)入下一次循環(huán)。 其實(shí),遍歷,就相當(dāng)于把每一個(gè)元素,在代碼中從上到下寫下來。當(dāng)它們處于async函數(shù)中,并在每個(gè)元素前面加await,它們自然就能串行執(zhí)行。否則,我們都知道,簡(jiǎn)單的從上到下寫下來的異步任務(wù),它們還是并行執(zhí)行的。

好了,現(xiàn)在程序不報(bào)錯(cuò)了。但是,1000多個(gè)任務(wù)依次執(zhí)行完成,足足花了十多分鐘,太慢了!有沒有辦法,又快又不觸發(fā)接口調(diào)用限制呢?

有,如果可以并行200個(gè)任務(wù),完成后再開始下一輪200個(gè)......也就是,把并行和串行相結(jié)合。

 

三、并行串行結(jié)合


async function bingChuan(arr, num) {
    let items = arr.splice(0, num);
    
    await Promise.all(items.map(i => i()));    
    if (arr.length > 0) {
        await bingChuan(arr, num);
    }
}
bingChuan(arr, 2);// 2結(jié)束// 1結(jié)束// 3結(jié)束


查看原文


該文章在 2023/10/27 17:42:55 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved