forked from vercel/next.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathp-queue.js
83 lines (76 loc) · 1.61 KB
/
p-queue.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// 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
}
}