maximize-iterator
Version:
Maximize the parallel calls of an iterator supporting asyncIterator interface
49 lines (48 loc) • 1.96 kB
JavaScript
import compat from 'async-compat';
const isError = (err)=>err && err.stack !== undefined && err.message !== undefined;
function processDone(err, options, callback) {
// mark this iteration done
options.err = options.err || err;
options.done = true;
// process done
if (!options.done || options.counter > 0) return false;
callback(options.err, options.done);
return true;
}
function processResult(err, keep, options, callback) {
options.counter--;
// mark this iteration done
if (err && compat.defaultValue(options.error(err), false) || !err && !compat.defaultValue(keep, true)) {
options.err = options.err || err;
options.done = true;
}
// process done
if (!options.done || options.counter > 0) return false;
callback(options.err, options.done);
return true;
}
export default function createProcessor(next, options, callback) {
let isProcessing = false;
return function processor(doneOrError) {
const error = doneOrError;
if (doneOrError && processDone(isError(error) ? error : null, options, callback)) return;
if (isProcessing) return;
isProcessing = true;
while(options.counter < options.concurrency){
if (options.done || !options.canProcess()) break;
if (options.total >= options.limit) {
processDone(null, options, callback);
return;
}
options.total++;
options.counter++;
next((err, result)=>{
if (err || result.done) {
return !processResult(err, false, options, callback) && !isProcessing ? processor() : undefined;
}
compat.asyncFunction(options.each, options.callbacks, result.value, (err, keep)=>!processResult(err, keep, options, callback) && !isProcessing ? processor() : undefined);
});
}
isProcessing = false;
};
}