From b8d1115888c335bdf55d53fa0a943859420c259c Mon Sep 17 00:00:00 2001 From: Hubert Argasinski Date: Sun, 13 Feb 2022 19:45:39 -0500 Subject: [PATCH] only run drain once when multiple empty tasks are pushed [#1791] --- lib/internal/queue.js | 10 ++++++++-- test/queue.js | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/lib/internal/queue.js b/lib/internal/queue.js index 886fe7ab1..fdbabbcf5 100644 --- a/lib/internal/queue.js +++ b/lib/internal/queue.js @@ -45,6 +45,7 @@ export default function queue(worker, concurrency, payload) { } var processingScheduled = false; + var drainScheduled = false; function _insert(data, insertAtFront, rejectOnError, callback) { if (callback != null && typeof callback !== 'function') { throw new Error('task callback must be a function'); @@ -124,7 +125,13 @@ export default function queue(worker, concurrency, payload) { function _maybeDrain(data) { if (data.length === 0 && q.idle()) { // call drain immediately if there are no tasks - setImmediate(() => trigger('drain')); + if (!drainScheduled) { + drainScheduled = true + setImmediate(() => { + trigger('drain') + drainScheduled = false + }) + } return true } return false @@ -141,7 +148,6 @@ export default function queue(worker, concurrency, payload) { } off(name) on(name, handler) - } var isProcessing = false; diff --git a/test/queue.js b/test/queue.js index f99e91af4..bd71b052c 100644 --- a/test/queue.js +++ b/test/queue.js @@ -670,6 +670,46 @@ describe('queue', function(){ done(); }); + it('should only call drain once when empty tasks are pushed', (done) => { + const q = async.queue(() => { + throw new Error('should not be called') + }) + + let numCalled = 0 + q.drain(() => { + numCalled++ + }) + q.push([]) + q.push([]) + q.push([]) + + setTimeout(() => { + expect(numCalled).to.equal(1) + done() + }, 50); + }); + + it('should not schedule another drain call if one is running', (done) => { + const q = async.queue(() => { + throw new Error('should not be called') + }) + + let numCalled = 0 + q.drain(() => { + if (numCalled > 0) { + throw new Error('drain should not be called more than one') + } + numCalled++ + q.push([]) + }) + q.push([]) + + setTimeout(() => { + expect(numCalled).to.equal(1) + done() + }, 50); + }); + context('q.saturated(): ', () => { it('should call the saturated callback if tasks length is concurrency', (done) => { var calls = [];