Last active
May 11, 2020 13:47
-
-
Save nc7s/abba4de6e0380309cfb33ef5404810b4 to your computer and use it in GitHub Desktop.
Run multiple requests with a limit on concurrent requests.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; const [multiRequest, makeRequestFunc] = (() => { | |
let globalRequestPool = [], | |
globalProcessingPool = [], | |
globalMaxConcurrentRequests = 5, /* Give it a default */ | |
globalRequestFunc = null, | |
globalProcessPoolFunc = null | |
type RequestOptions = { | |
isGlobal: boolean, | |
requestFunc: Function | |
} | |
function _makeProcessPoolFunc(requestPool: Array<PromisedRequest>, processingPool: Array<Promise<any>>, maxConcurrentRequests: number, requestFunc: Function) { | |
function hasFinished(finishedRequest) { | |
if(finishedRequest) { | |
processingPool.splice(processingPool.indexOf(finishedRequest), 1) | |
} | |
if(processingPool.length < maxConcurrentRequests && requestPool.length != 0) { | |
processingPool.push(requestPool.shift().run(hasFinished)) | |
} | |
} | |
return function processPoolFunc() { | |
while(processingPool.length < maxConcurrentRequests) { | |
hasFinished(null) | |
} | |
} | |
} | |
class MultiRequest { | |
private _requests: Array<PromisedRequest> | |
constructor(requests: PromisedRequest | Array<PromisedRequest>, max: number, options: RequestOptions = { | |
isGlobal: true, | |
requestFunc: fetch | |
}) { | |
if(requests instanceof PromisedRequest) { | |
requests = [requests] | |
} | |
this._requests = requests | |
if(options.isGlobal) { | |
globalRequestPool = globalRequestPool.concat(requests) | |
if(max != globalMaxConcurrentRequests || options.requestFunc != globalRequestFunc || !globalProcessPoolFunc) { | |
globalMaxConcurrentRequests = max | |
globalRequestFunc = options.requestFunc | |
globalProcessPoolFunc = _makeProcessPoolFunc(globalRequestPool, globalProcessingPool, max, globalRequestFunc) | |
globalProcessPoolFunc() | |
} | |
} else { | |
_makeProcessPoolFunc([].concat(requests), [], max, options.requestFunc)() | |
} | |
} | |
then(thenFunc) { | |
for(let request of this._requests) { | |
request.then(thenFunc) | |
} | |
} | |
catch(catchFunc) { | |
for(let request of this._requests) { | |
request.catch(catchFunc) | |
} | |
} | |
finally(finallyFunc) { | |
for(let request of this._requests) { | |
request.finally(finallyFunc) | |
} | |
} | |
} | |
class PromisedRequest { | |
private _requestFunc: Function | |
private _args: Array<any> | |
private _thenFuncs: Array<Function> | |
private _catchFuncs: Array<Function> | |
private _finallyFuncs: Array<Function> | |
constructor(requestFunc, args: Array<any>) { | |
this._requestFunc = requestFunc | |
this._args = args | |
} | |
then(thenFunc: Function) { this._thenFuncs.push(thenFunc) } | |
catch(catchFunc: Function) { this._catchFuncs.push(catchFunc) } | |
finally(finallyFunc: Function) { this._finallyFuncs.push(finallyFunc) } | |
run(hasFinishedFunc) { | |
let promise = this._requestFunc.apply(this._requestFunc, this._args) | |
for(let thenFunc of this._thenFuncs) { | |
promise = promise.then(thenFunc) | |
} | |
if(this._catchFuncs.length != 0) { | |
promise = promise.catch(reason => { | |
for(let catchFunc of this._catchFuncs) { | |
catchFunc(reason) | |
} | |
}) | |
} | |
promise = promise.finally(() => { | |
if(this._finallyFuncs.length != 0) { | |
for(let finallyFunc of this._finallyFuncs) { | |
finallyFunc() | |
} | |
} | |
hasFinishedFunc(this) | |
}) | |
return promise | |
} | |
} | |
function multiRequest(requests: PromisedRequest | Array<PromisedRequest>, max: number, options: RequestOptions) { | |
return new MultiRequest(requests, max, options) | |
} | |
function makeRequestFunc(requestFunc) { | |
return function request(...args) { | |
return new PromisedRequest(requestFunc, args) | |
} | |
} | |
return [multiRequest, makeRequestFunc] | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment