Skip to content

Commit

Permalink
Add .onSizeLessThan() helper method (#131)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <[email protected]>
  • Loading branch information
dobesv and sindresorhus authored Mar 31, 2021
1 parent 1ed5b4c commit 8d0a356
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 0 deletions.
8 changes: 8 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,14 @@ Returns a promise that settles when the queue becomes empty, and all promises ha

The 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.

#### .onSizeLessThan(limit)

Returns a promise that settles when the queue size is less than the given limit: `queue.size < limit`.

If you want to avoid having the queue grow beyond a certain size you can `await queue.onSizeLessThan()` before adding a new item.

Note that this only limits the number of items waiting to start. There could still be up to `concurrency` jobs already running that this call does not include in its calculation.

#### .clear()

Clear the queue.
Expand Down
25 changes: 25 additions & 0 deletions source/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,31 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
});
}

/**
@returns A promise that settles when the queue size is less than the given limit: `queue.size < limit`.
If you want to avoid having the queue grow beyond a certain size you can `await queue.onSizeLessThan()` before adding a new item.
Note that this only limits the number of items waiting to start. There could still be up to `concurrency` jobs already running that this call does not include in its calculation.
*/
async onSizeLessThan(limit: number): Promise<void> {
// Instantly resolve if the queue is empty.
if (this._queue.size < limit) {
return;
}

return new Promise<void>(resolve => {
const listener = () => {
if (this._queue.size < limit) {
this.removeListener('next', listener);
resolve();
}
};

this.on('next', listener);
});
}

/**
The 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.
Expand Down
26 changes: 26 additions & 0 deletions test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,32 @@ test('.onIdle()', async t => {
t.is(queue.pending, 0);
});

test('.onSizeLessThan()', async t => {
const queue = new PQueue({concurrency: 1});

queue.add(async () => delay(100));
queue.add(async () => delay(100));
queue.add(async () => delay(100));
queue.add(async () => delay(100));
queue.add(async () => delay(100));

await queue.onSizeLessThan(4);
t.is(queue.size, 3);
t.is(queue.pending, 1);

await queue.onSizeLessThan(2);
t.is(queue.size, 1);
t.is(queue.pending, 1);

await queue.onSizeLessThan(10);
t.is(queue.size, 1);
t.is(queue.pending, 1);

await queue.onSizeLessThan(1);
t.is(queue.size, 0);
t.is(queue.pending, 1);
});

test('.onIdle() - no pending', async t => {
const queue = new PQueue();
t.is(queue.size, 0);
Expand Down

0 comments on commit 8d0a356

Please sign in to comment.