JavaScript實(shí)現(xiàn)控制并發(fā)請(qǐng)求數(shù)量的方法詳解
前言
嗨呀,又是將近一個(gè)月沒(méi)有更文了,想死你們了!今天又來(lái)繼續(xù)我的更文事業(yè),技術(shù)的道路注定是要將卷進(jìn)行到底的!至于這么久才來(lái)更文的原因,那自然是沒(méi)有好的羊毛值得去薅,一旦有好羊毛那當(dāng)然是也不會(huì)缺席的,所以今天我來(lái)了!
這次要分享的主題就是前久飯后在和同事討論時(shí)無(wú)意間發(fā)現(xiàn)的,那就是前端如何實(shí)現(xiàn)并發(fā)請(qǐng)求數(shù)量控制。如果你在實(shí)際項(xiàng)目中有過(guò)類似的需求,應(yīng)該不會(huì)陌生,反之如果你還沒(méi)有且還不了解的話,那你就有必要耐心地看完這篇文章,保證你一定會(huì)有所收獲的!
場(chǎng)景
假設(shè)有這么一個(gè)場(chǎng)景:現(xiàn)在有20
個(gè)異步請(qǐng)求需要發(fā)送,但是由于某些原因,要求我們必須將同一時(shí)刻的并發(fā)請(qǐng)求數(shù)量控制在3
個(gè)以內(nèi),并且還要盡可能快速的拿到響應(yīng)結(jié)果。其實(shí)這個(gè)場(chǎng)景在一些大廠的面試題中也有過(guò)提及,如下:
實(shí)現(xiàn)一個(gè)并發(fā)請(qǐng)求函數(shù)concurrencyRequest(urls, maxNum),要求如下:
• 要求最大并發(fā)數(shù) maxNum
• 每當(dāng)有一個(gè)請(qǐng)求返回,就留下一個(gè)空位,可以增加新的請(qǐng)求
• 所有請(qǐng)求完成后,結(jié)果按照 urls 里面的順序依次打出(發(fā)送請(qǐng)求的函數(shù)可以直接使用fetch即可)
遇到到這個(gè)問(wèn)題時(shí)你會(huì)怎么來(lái)做?
遇到這個(gè)問(wèn)題還是先來(lái)分析一下這個(gè)問(wèn)題的設(shè)計(jì)思路→。
設(shè)計(jì)思路
首先來(lái)看將上面的文字轉(zhuǎn)化為圖之后的效果:
這樣就直觀的看到,有一個(gè)最大并發(fā)數(shù)maxNum
,20
個(gè)異步請(qǐng)求的urls
集合和并發(fā)返回之后的results
集合。
下面就開始演示這個(gè)思路是如何開始的,如下:
首先按照每次只能并發(fā)3
個(gè)請(qǐng)求的要求,這里就對(duì)應(yīng)A、B、C
,當(dāng)其中有一個(gè)請(qǐng)求完之后就會(huì)再?gòu)?code>urls里面再取出一個(gè)進(jìn)行請(qǐng)求,這樣依次類推,直到urls
里面的20
個(gè)請(qǐng)求都執(zhí)行完才終止請(qǐng)求。
主要思路就是上面所述,但是在開發(fā)時(shí)我們要考慮一些特殊情況,如下:
urls
的長(zhǎng)度為0
時(shí),results
就沒(méi)有值,此時(shí)應(yīng)該返回空數(shù)組maxNum
大于urls
的長(zhǎng)度時(shí),應(yīng)該取的是urls
的長(zhǎng)度,否則則是取maxNum
- 需要定義一個(gè)
count
計(jì)數(shù)器來(lái)判斷是否已全部請(qǐng)求完成 - 因?yàn)闆](méi)有考慮請(qǐng)求是否請(qǐng)求成功,所以請(qǐng)求成功或報(bào)錯(cuò)都應(yīng)把結(jié)果保存在
results
集合中 results
中的順序需和urls
中的保持一致
好,我的設(shè)計(jì)思路就是這樣的,下面就要來(lái)開始開發(fā)工作啦~
開發(fā)
具體代碼如下(代碼中已備注有注釋):
// 并發(fā)請(qǐng)求函數(shù) const concurrencyRequest = (urls, maxNum) => { return new Promise((resolve) => { if (urls.length === 0) { resolve([]); return; } const results = []; let index = 0; // 下一個(gè)請(qǐng)求的下標(biāo) let count = 0; // 當(dāng)前請(qǐng)求完成的數(shù)量 // 發(fā)送請(qǐng)求 async function request() { if (index === urls.length) return; const i = index; // 保存序號(hào),使result和urls相對(duì)應(yīng) const url = urls[index]; index++; console.log(url); try { const resp = await fetch(url); // resp 加入到results results[i] = resp; } catch (err) { // err 加入到results results[i] = err; } finally { count++; // 判斷是否所有的請(qǐng)求都已完成 if (count === urls.length) { console.log('完成了'); resolve(results); } request(); } } // maxNum和urls.length取最小進(jìn)行調(diào)用 const times = Math.min(maxNum, urls.length); for(let i = 0; i < times; i++) { request(); } }) }
測(cè)試
測(cè)試代碼如下:
const urls = []; for (let i = 1; i <= 20; i++) { urls.push(`https://jsonplaceholder.typicode.com/todos/${i}`); } concurrencyRequest(urls, 3).then(res => { console.log(res); })
結(jié)果
下面通過(guò)運(yùn)行代碼來(lái)看看效果:
首先來(lái)看看控制臺(tái)輸出的結(jié)果,如下:
可以看到20
個(gè)請(qǐng)求都請(qǐng)求完成,results
里面也是按順序打印出了結(jié)果。
然后再看看請(qǐng)求時(shí)請(qǐng)求數(shù)量是否每次都是3
個(gè),如下:
通過(guò)上面這個(gè)gif
圖可以很直觀的看到,每次請(qǐng)求的數(shù)量都是3
個(gè),證明寫的代碼沒(méi)有毛病,搞定!
至此,這個(gè)在實(shí)際開發(fā)中會(huì)遇見的前端控制并發(fā)請(qǐng)求的需求就實(shí)現(xiàn)完成了。代碼相對(duì)來(lái)說(shuō)沒(méi)有太大的難度,只要把一些特殊情況給考慮完全,最后的實(shí)現(xiàn)也就沒(méi)什么太大問(wèn)題。最后,希望看完這篇文章之后你也能輕松掌握前端控制并發(fā)數(shù)量的問(wèn)題,栓Q~
以上就是JavaScript實(shí)現(xiàn)控制并發(fā)請(qǐng)求數(shù)量的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于JavaScript控制并發(fā)請(qǐng)求數(shù)量的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序scroll-view實(shí)現(xiàn)左右聯(lián)動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了微信小程序scroll-view實(shí)現(xiàn)左右聯(lián)動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09使用JavaScript實(shí)現(xiàn)檢測(cè)網(wǎng)頁(yè)是否為空閑狀態(tài)
最近開發(fā)項(xiàng)目時(shí),常碰到“用戶在一定時(shí)間內(nèi)無(wú)任何操作時(shí),跳轉(zhuǎn)到某個(gè)頁(yè)面”的需求,所以本文就來(lái)使用JavaScript實(shí)現(xiàn)這一要求,需要的可以參考下2024-03-03原生JS實(shí)現(xiàn)簡(jiǎn)單的輪播圖效果
這篇文章主要為大家詳細(xì)介紹了原生JS實(shí)現(xiàn)簡(jiǎn)單的輪播圖效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07JS簡(jiǎn)單測(cè)試循環(huán)運(yùn)行時(shí)間的方法
這篇文章主要介紹了JS簡(jiǎn)單測(cè)試循環(huán)運(yùn)行時(shí)間的方法,涉及針對(duì)javascript中for循環(huán)、for...in循環(huán)及foreach循環(huán)的相關(guān)使用方法及運(yùn)行時(shí)間測(cè)試,需要的朋友可以參考下2016-09-09JS實(shí)現(xiàn)拖動(dòng)模態(tài)框案例
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)拖動(dòng)模態(tài)框案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07微信域名檢測(cè)接口調(diào)用演示步驟(含PHP、Python)
這篇文章主要介紹了微信域名檢測(cè)接口調(diào)用演示步驟(含PHP、Python),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12概述BootStrap中role="form"及role作用角色
這篇文章主要介紹了BootStrap中role="form"及role作用角色介紹,以及bootstrap柵欄系統(tǒng)css中的col-xs-*,col-sm-*,col-md-* 的意義簡(jiǎn)單介紹,需要的朋友參考下2016-12-12