Last active
June 28, 2018 04:14
-
-
Save ccnokes/068d74fcf9b19347b6dcd6f5134516d1 to your computer and use it in GitHub Desktop.
Task queue with configurable concurrency and priority. Demo: https://jsfiddle.net/ccnokes/6hb92mde/
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
// see demo: https://jsfiddle.net/ccnokes/6hb92mde/ | |
class Deferred { | |
constructor() { | |
this.promise = new Promise((resolve, reject) => { | |
this.resolve = resolve; | |
this.reject = reject; | |
}); | |
this.then = this.promise.then.bind(this.promise); | |
this.catch = this.promise.catch.bind(this.promise); | |
} | |
} | |
class TaskQueue { | |
constructor(concurrency = 3) { | |
this.tasks = []; | |
this.pending = []; | |
this.concurrency = concurrency; | |
} | |
get isRunning() { | |
return this.pending.length >= this.concurrency; | |
} | |
run() { | |
if (this.pending.length < this.concurrency && this.tasks.length > 0) { | |
let next = this.tasks.shift(); | |
let promise; | |
let onComplete = resultOrErr => { | |
this.pending.splice(this.pending.indexOf(promise), 1); | |
this.run(); | |
if (resultOrErr instanceof Error) { | |
next.complete.reject(resultOrErr); | |
throw resultOrErr; | |
} else { | |
next.complete.resolve(resultOrErr); | |
return resultOrErr; | |
} | |
} | |
promise = next.fn().then(onComplete).catch(onComplete); | |
this.pending.push(promise); | |
this.run(); | |
} | |
} | |
add(...tasks) { | |
let needsSort = false; | |
let ret = tasks.map(task => { | |
let isFunction = typeof task === 'function'; | |
needsSort = isFunction; | |
let taskObj = isFunction ? | |
{ fn: task, priority: 0, complete: new Deferred() } : | |
Object.assign(task, { complete: new Deferred() }) | |
; | |
this.tasks.push(taskObj); | |
return taskObj.complete; | |
}); | |
if (needsSort) { | |
this.tasks.sort((a, b) => b.priority - a.priority); | |
} | |
if (!this.isRunning) { | |
this.run(); | |
} | |
return Promise.all(ret); | |
} | |
delete(fn) { | |
let index = this.tasks.find(task => task.fn === fn); | |
if (index > -1) { | |
this.tasks.splice(index, 1); | |
} | |
} | |
clear() { | |
this.tasks = []; | |
this.pending = []; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment