@antora/assembler
Version:
An extension library for Antora that assembles content from multiple pages into a single AsciiDoc file to converted and publish.
58 lines (52 loc) • 1.5 kB
JavaScript
'use strict'
class PromiseQueue {
#scheduler
#started
#pending
#rejection
#startTask
#trapRejection
constructor ({ concurrency = Infinity } = {}) {
this.concurrency = concurrency
this.#scheduler = Promise.resolve()
this.#started = []
this.#pending = []
this.#startTask = (task) => {
if (this.#rejection) return
if (this.concurrency === Infinity) {
this.#started.push(task().catch(this.#trapRejection))
} else {
let current
this.#pending.push(
(current = task()
.catch(this.#trapRejection)
.finally(() => this.#pending.splice(this.#pending.indexOf(current), 1)))
)
this.#started.push(current)
}
}
this.#trapRejection = (err) => (this.#rejection = err || new Error()) && undefined
}
add (tasks) {
if (!Array.isArray(tasks)) tasks = [tasks]
for (const task of tasks) {
if (this.#pending.length < this.concurrency) {
this.#startTask(task)
} else {
this.#scheduler = this.#scheduler.then(
() => this.#pending.length && Promise.race(this.#pending).then(() => this.#startTask(task))
)
}
}
return this
}
async toPromise () {
// what about promiseAll(), all(), or promise()?
await this.#scheduler
return Promise.all(this.#started).then((returnValues) => {
if (this.#rejection) throw this.#rejection
return returnValues
})
}
}
module.exports = PromiseQueue