UNPKG

7.69 kBMarkdownView Raw
1# p-queue [![Build Status](https://travis-ci.org/sindresorhus/p-queue.svg?branch=master)](https://travis-ci.org/sindresorhus/p-queue) [![codecov](https://codecov.io/gh/sindresorhus/p-queue/branch/master/graph/badge.svg)](https://codecov.io/gh/sindresorhus/p-queue)
2
3> Promise queue with concurrency control
4
5Useful for rate-limiting async (or sync) operations. For example, when interacting with a REST API or when doing CPU/memory intensive tasks.
6
7
8## Install
9
10```
11$ npm install p-queue
12```
13
14
15## Usage
16
17Here we run only one promise at the time. For example, set `concurrency` to 4 to run four promises at the same time.
18
19```js
20const {default: PQueue} = require('p-queue');
21const got = require('got');
22
23const queue = new PQueue({concurrency: 1});
24
25(async () => {
26 await queue.add(() => got('sindresorhus.com'));
27 console.log('Done: sindresorhus.com');
28})();
29
30(async () => {
31 await queue.add(() => got('ava.li'));
32 console.log('Done: ava.li');
33})();
34
35(async () => {
36 const task = await getUnicornTask();
37 await queue.add(task);
38 console.log('Done: Unicorn task');
39})();
40```
41
42
43## API
44
45### PQueue(options?)
46
47Returns a new `queue` instance, which is an [`EventEmitter3`](https://github.com/primus/eventemitter3) subclass.
48
49#### options
50
51Type: `object`
52
53##### concurrency
54
55Type: `number`\
56Default: `Infinity`\
57Minimum: `1`
58
59Concurrency limit.
60
61##### timeout
62
63Type: `number`
64
65Per-operation timeout in milliseconds. Operations fulfill once `timeout` elapses if they haven't already.
66
67##### throwOnTimeout
68
69Type: `boolean`\
70Default: `false`
71
72Whether or not a timeout is considered an exception.
73
74##### autoStart
75
76Type: `boolean`\
77Default: `true`
78
79Whether queue tasks within concurrency limit, are auto-executed as soon as they're added.
80
81##### queueClass
82
83Type: `Function`
84
85Class with a `enqueue` and `dequeue` method, and a `size` getter. See the [Custom QueueClass](#custom-queueclass) section.
86
87##### intervalCap
88
89Type: `number`\
90Default: `Infinity`\
91Minimum: `1`
92
93The max number of runs in the given interval of time.
94
95##### interval
96
97Type: `number`\
98Default: `0`\
99Minimum: `0`
100
101The length of time in milliseconds before the interval count resets. Must be finite.
102
103##### carryoverConcurrencyCount
104
105Type: `boolean`\
106Default: `false`
107
108Whether the task must finish in the given interval or will be carried over into the next interval count.
109
110### queue
111
112`PQueue` instance.
113
114#### .add(fn, options?)
115
116Adds a sync or async task to the queue. Always returns a promise.
117
118##### fn
119
120Type: `Function`
121
122Promise-returning/async function.
123
124#### options
125
126Type: `object`
127
128##### priority
129
130Type: `number`\
131Default: `0`
132
133Priority of operation. Operations with greater priority will be scheduled first.
134
135#### .addAll(fns, options?)
136
137Same as `.add()`, but accepts an array of sync or async functions and returns a promise that resolves when all functions are resolved.
138
139#### .pause()
140
141Put queue execution on hold.
142
143#### .start()
144
145Start (or resume) executing enqueued tasks within concurrency limit. No need to call this if queue is not paused (via `options.autoStart = false` or by `.pause()` method.)
146
147Returns `this` (the instance).
148
149#### .onEmpty()
150
151Returns a promise that settles when the queue becomes empty.
152
153Can be called multiple times. Useful if you for example add additional items at a later time.
154
155#### .onIdle()
156
157Returns a promise that settles when the queue becomes empty, and all promises have completed; `queue.size === 0 && queue.pending === 0`.
158
159The difference with `.onEmpty` is that `.onIdle` guarantees that all work from the queue has finished. `.onEmpty` merely signals that the queue is empty, but it could mean that some promises haven't completed yet.
160
161#### .clear()
162
163Clear the queue.
164
165#### .size
166
167Size of the queue.
168
169
170#### .sizeBy(options)
171
172Size of the queue, filtered by the given options.
173
174For example, this can be used to find the number of items remaining in the queue with a specific priority level.
175
176```js
177const queue = new PQueue();
178
179queue.add(async () => 'πŸ¦„', {priority: 1});
180queue.add(async () => 'πŸ¦„', {priority: 0});
181queue.add(async () => 'πŸ¦„', {priority: 1});
182
183console.log(queue.sizeBy({priority: 1}));
184//=> 2
185
186console.log(queue.sizeBy({priority: 0}));
187//=> 1
188```
189
190#### .pending
191
192Number of pending promises.
193
194#### [.timeout](#timeout)
195
196#### [.concurrency](#concurrency)
197
198#### .isPaused
199
200Whether the queue is currently paused.
201
202
203## Events
204
205#### active
206
207Emitted as each item is processed in the queue for the purpose of tracking progress.
208
209```js
210const delay = require('delay');
211const {default: PQueue} = require('p-queue');
212
213const queue = new PQueue({concurrency: 2});
214
215let count = 0;
216queue.on('active', () => {
217 console.log(`Working on item #${++count}. Size: ${queue.size} Pending: ${queue.pending}`);
218});
219
220queue.add(() => Promise.resolve());
221queue.add(() => delay(2000));
222queue.add(() => Promise.resolve());
223queue.add(() => Promise.resolve());
224queue.add(() => delay(500));
225```
226
227
228## Advanced example
229
230A more advanced example to help you understand the flow.
231
232```js
233const delay = require('delay');
234const {default: PQueue} = require('p-queue');
235
236const queue = new PQueue({concurrency: 1});
237
238(async () => {
239 await delay(200);
240
241 console.log(`8. Pending promises: ${queue.pending}`);
242 //=> '8. Pending promises: 0'
243
244 (async () => {
245 await queue.add(async () => 'πŸ™');
246 console.log('11. Resolved')
247 })();
248
249 console.log('9. Added πŸ™');
250
251 console.log(`10. Pending promises: ${queue.pending}`);
252 //=> '10. Pending promises: 1'
253
254 await queue.onIdle();
255 console.log('12. All work is done');
256})();
257
258(async () => {
259 await queue.add(async () => 'πŸ¦„');
260 console.log('5. Resolved')
261})();
262console.log('1. Added πŸ¦„');
263
264(async () => {
265 await queue.add(async () => '🐴');
266 console.log('6. Resolved')
267})();
268console.log('2. Added 🐴');
269
270(async () => {
271 await queue.onEmpty();
272 console.log('7. Queue is empty');
273})();
274
275console.log(`3. Queue size: ${queue.size}`);
276//=> '3. Queue size: 1`
277
278console.log(`4. Pending promises: ${queue.pending}`);
279//=> '4. Pending promises: 1'
280```
281
282```
283$ node example.js
2841. Added πŸ¦„
2852. Added 🐴
2863. Queue size: 1
2874. Pending promises: 1
2885. Resolved πŸ¦„
2896. Resolved 🐴
2907. Queue is empty
2918. Pending promises: 0
2929. Added πŸ™
29310. Pending promises: 1
29411. Resolved πŸ™
29512. All work is done
296```
297
298
299## Custom QueueClass
300
301For implementing more complex scheduling policies, you can provide a QueueClass in the options:
302
303```js
304class QueueClass {
305 constructor() {
306 this._queue = [];
307 }
308
309 enqueue(run, options) {
310 this._queue.push(run);
311 }
312
313 dequeue() {
314 return this._queue.shift();
315 }
316
317 get size() {
318 return this._queue.length;
319 }
320
321 filter(options) {
322 return this._queue;
323 }
324}
325```
326
327`p-queue` will call corresponding methods to put and get operations from this queue.
328
329
330## Related
331
332- [p-limit](https://github.com/sindresorhus/p-limit) - Run multiple promise-returning & async functions with limited concurrency
333- [p-throttle](https://github.com/sindresorhus/p-throttle) - Throttle promise-returning & async functions
334- [p-debounce](https://github.com/sindresorhus/p-debounce) - Debounce promise-returning & async functions
335- [p-all](https://github.com/sindresorhus/p-all) - Run promise-returning & async functions concurrently with optional limited concurrency
336- [More…](https://github.com/sindresorhus/promise-fun)
337
338
339---
340
341<div align="center">
342 <b>
343 <a href="https://tidelift.com/subscription/pkg/npm-p-queue?utm_source=npm-p-queue&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
344 </b>
345 <br>
346 <sub>
347 Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
348 </sub>
349</div>