Skip to content

Instantly share code, notes, and snippets.

@nc7s
Last active May 11, 2020 13:47
Show Gist options
  • Save nc7s/abba4de6e0380309cfb33ef5404810b4 to your computer and use it in GitHub Desktop.
Save nc7s/abba4de6e0380309cfb33ef5404810b4 to your computer and use it in GitHub Desktop.
Run multiple requests with a limit on concurrent requests.
; 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