使用 Promise 實(shí)現(xiàn)任務(wù)隊(duì)列發(fā)送請(qǐng)求,實(shí)現(xiàn)最大請(qǐng)求數(shù)目限制
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
? 作者?|??一只菜鳥攻城獅啊?
來源 |? urlify.cn/RBrIbu
66套java從入門到精通實(shí)戰(zhàn)課程分享?
核心
設(shè)置最大請(qǐng)求數(shù)量,當(dāng)前請(qǐng)求數(shù)量,待執(zhí)行隊(duì)列
調(diào)用時(shí),創(chuàng)建一個(gè)新任務(wù),然后判斷是否達(dá)到最大請(qǐng)求數(shù)量,若達(dá)到則將任務(wù)追加到待執(zhí)行隊(duì)列,否則,則直接執(zhí)行該任務(wù)。并返回Promise
創(chuàng)建任務(wù)時(shí),需要返回一個(gè)函數(shù),當(dāng)該任務(wù)開始執(zhí)行則當(dāng)前數(shù)量加一。當(dāng)任務(wù)執(zhí)行完畢時(shí)使用finally,當(dāng)前數(shù)量減一,并從待執(zhí)行隊(duì)列中取出新任務(wù)執(zhí)行
實(shí)現(xiàn)
class?limitPromise{
????constructor(max){
????this.max?=?max;
????this._count?=?0;
????this._pendingTaskQueue?=?[];
??}
???/**
???*?調(diào)用器,將異步任務(wù)函數(shù)和它的參數(shù)傳入
???*?@param?caller?異步任務(wù)函數(shù),返回Promise的函數(shù)
???*?@param?args?異步任務(wù)函數(shù)的參數(shù)列表
???*?@returns?{Promise}?返回一個(gè)新的Promise
???*/
??call?=?(caller,?...arg)?=>?{
????return?new?Promise((resolve,?reject)?=>?{
????????let?task?=?this._createTask(caller,?arg,?resolve,?reject);
????????if(this._count?>=?this.max)?{
????????this._pendingTaskQueue.push();
????????}else{
????????task();
????????}
????});
????}
???/**
???*?創(chuàng)建一個(gè)任務(wù)
???*?@param?caller?實(shí)際執(zhí)行的函數(shù)
???*?@param?args?執(zhí)行函數(shù)的參數(shù)
???*?@param?resolve
???*?@param?reject
???*?@returns?{Function}?返回一個(gè)任務(wù)函數(shù)
???*?@private
???*/
?????_createTask?=?(caller,?arg,?resolve,?reject)=>?{
?????return?()?=>?{
???????//?當(dāng)前請(qǐng)求數(shù)量加一
???????this._count++;
???????//?實(shí)際上是在這里調(diào)用了異步任務(wù),并將異步任務(wù)的返回(resolve和reject)拋給了上層
???????caller(...arg)
?????????.then(resolve)
?????????.catch(reject)
?????????.finally(()?=>?{
????????????????//?任務(wù)隊(duì)列的消費(fèi)區(qū),利用Promise的finally方法,在異步任務(wù)結(jié)束后,取出下一個(gè)任務(wù)執(zhí)行
????????????????this._count--;
????????????????if(this._pendingTaskQueue.length){
????????????????let?task?=?this._pendingTaskQueue.shift();
????????????????task();
????????????????}?
????????})
?????}
???}
}
使用
假設(shè)我們有一個(gè)網(wǎng)絡(luò)請(qǐng)求模塊,叫request.js,包含get和post方法,一般情況下,是這樣使用的
const?request?=?require('./request')
request.get('https://www.baidu.com')
??.then((res)?=>?{
????//?處理返回結(jié)果
??})
??.catch(err?=>?{
????//?處理異常情況
??})
現(xiàn)在我們要把它改造成受限制的網(wǎng)絡(luò)請(qǐng)求,假設(shè)請(qǐng)求上限設(shè)為10個(gè),并起名叫l(wèi)imitRequest.js。實(shí)現(xiàn)如下:
const?LimitPromise?=?require('limit-promise')
const?request?=?require('./request')
//?請(qǐng)求上限
const?MAX?=?10
//?核心控制器
const?limitP?=?new?LimitPromise(MAX)
//?利用核心控制器包裝request中的函數(shù)
function?get?(url,?params)?{
??return?limitP.call(request.get,?url,?params)
}
function?post?(url,?params)?{
??return?limitP.call(request.post,?url,?params)
}
//?導(dǎo)出
module.exports?=?{get,?post}
這里就完成受限請(qǐng)求模塊的構(gòu)建了,是不是很簡單,而且調(diào)用接口完全沒變,只需要引入limitRequest.js替代原先的即可。


??? ?
感謝點(diǎn)贊支持下哈?
