You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
62 lines
1.4 KiB
62 lines
1.4 KiB
/* |
|
MIT License http://www.opensource.org/licenses/mit-license.php |
|
Author Tobias Koppers @sokra |
|
*/ |
|
|
|
"use strict"; |
|
|
|
/** |
|
* @template T |
|
* @template {Error} E |
|
* @param {Iterable<T>} items initial items |
|
* @param {number} concurrency number of items running in parallel |
|
* @param {function(T, function(T): void, function(E=): void): void} processor worker which pushes more items |
|
* @param {function(E=): void} callback all items processed |
|
* @returns {void} |
|
*/ |
|
const processAsyncTree = (items, concurrency, processor, callback) => { |
|
const queue = Array.from(items); |
|
if (queue.length === 0) return callback(); |
|
let processing = 0; |
|
let finished = false; |
|
let processScheduled = true; |
|
|
|
const push = item => { |
|
queue.push(item); |
|
if (!processScheduled && processing < concurrency) { |
|
processScheduled = true; |
|
process.nextTick(processQueue); |
|
} |
|
}; |
|
|
|
const processorCallback = err => { |
|
processing--; |
|
if (err && !finished) { |
|
finished = true; |
|
callback(err); |
|
return; |
|
} |
|
if (!processScheduled) { |
|
processScheduled = true; |
|
process.nextTick(processQueue); |
|
} |
|
}; |
|
|
|
const processQueue = () => { |
|
if (finished) return; |
|
while (processing < concurrency && queue.length > 0) { |
|
processing++; |
|
const item = queue.pop(); |
|
processor(item, push, processorCallback); |
|
} |
|
processScheduled = false; |
|
if (queue.length === 0 && processing === 0 && !finished) { |
|
finished = true; |
|
callback(); |
|
} |
|
}; |
|
|
|
processQueue(); |
|
}; |
|
|
|
module.exports = processAsyncTree;
|
|
|