mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
84 lines
1.6 KiB
JavaScript
84 lines
1.6 KiB
JavaScript
|
// based on https://github.com/sindresorhus/p-queue (MIT)
|
||
|
// modified for browser support
|
||
|
|
||
|
class Queue {
|
||
|
constructor () {
|
||
|
this._queue = []
|
||
|
}
|
||
|
enqueue (run) {
|
||
|
this._queue.push(run)
|
||
|
}
|
||
|
dequeue () {
|
||
|
return this._queue.shift()
|
||
|
}
|
||
|
get size () {
|
||
|
return this._queue.length
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export default class PQueue {
|
||
|
constructor (opts) {
|
||
|
opts = Object.assign({
|
||
|
concurrency: Infinity,
|
||
|
queueClass: Queue
|
||
|
}, opts)
|
||
|
|
||
|
if (opts.concurrency < 1) {
|
||
|
throw new TypeError('Expected `concurrency` to be a number from 1 and up')
|
||
|
}
|
||
|
|
||
|
this.queue = new opts.queueClass() // eslint-disable-line new-cap
|
||
|
this._pendingCount = 0
|
||
|
this._concurrency = opts.concurrency
|
||
|
this._resolveEmpty = () => {}
|
||
|
}
|
||
|
_next () {
|
||
|
this._pendingCount--
|
||
|
|
||
|
if (this.queue.size > 0) {
|
||
|
this.queue.dequeue()()
|
||
|
} else {
|
||
|
this._resolveEmpty()
|
||
|
}
|
||
|
}
|
||
|
add (fn, opts) {
|
||
|
return new Promise((resolve, reject) => {
|
||
|
const run = () => {
|
||
|
this._pendingCount++
|
||
|
|
||
|
fn().then(
|
||
|
val => {
|
||
|
resolve(val)
|
||
|
this._next()
|
||
|
},
|
||
|
err => {
|
||
|
reject(err)
|
||
|
this._next()
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
|
||
|
if (this._pendingCount < this._concurrency) {
|
||
|
run()
|
||
|
} else {
|
||
|
this.queue.enqueue(run, opts)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
onEmpty () {
|
||
|
return new Promise(resolve => {
|
||
|
const existingResolve = this._resolveEmpty
|
||
|
this._resolveEmpty = () => {
|
||
|
existingResolve()
|
||
|
resolve()
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
get size () {
|
||
|
return this.queue.size
|
||
|
}
|
||
|
get pending () {
|
||
|
return this._pendingCount
|
||
|
}
|
||
|
}
|