TransFlow/node_modules/batch-processor/src/batch-processor.js

139 lines
3.7 KiB
JavaScript

"use strict";
var utils = require("./utils");
module.exports = function batchProcessorMaker(options) {
options = options || {};
var reporter = options.reporter;
var asyncProcess = utils.getOption(options, "async", true);
var autoProcess = utils.getOption(options, "auto", true);
if(autoProcess && !asyncProcess) {
reporter && reporter.warn("Invalid options combination. auto=true and async=false is invalid. Setting async=true.");
asyncProcess = true;
}
var batch = Batch();
var asyncFrameHandler;
var isProcessing = false;
function addFunction(level, fn) {
if(!isProcessing && autoProcess && asyncProcess && batch.size() === 0) {
// Since this is async, it is guaranteed to be executed after that the fn is added to the batch.
// This needs to be done before, since we're checking the size of the batch to be 0.
processBatchAsync();
}
batch.add(level, fn);
}
function processBatch() {
// Save the current batch, and create a new batch so that incoming functions are not added into the currently processing batch.
// Continue processing until the top-level batch is empty (functions may be added to the new batch while processing, and so on).
isProcessing = true;
while (batch.size()) {
var processingBatch = batch;
batch = Batch();
processingBatch.process();
}
isProcessing = false;
}
function forceProcessBatch(localAsyncProcess) {
if (isProcessing) {
return;
}
if(localAsyncProcess === undefined) {
localAsyncProcess = asyncProcess;
}
if(asyncFrameHandler) {
cancelFrame(asyncFrameHandler);
asyncFrameHandler = null;
}
if(localAsyncProcess) {
processBatchAsync();
} else {
processBatch();
}
}
function processBatchAsync() {
asyncFrameHandler = requestFrame(processBatch);
}
function clearBatch() {
batch = {};
batchSize = 0;
topLevel = 0;
bottomLevel = 0;
}
function cancelFrame(listener) {
// var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.clearTimeout;
var cancel = clearTimeout;
return cancel(listener);
}
function requestFrame(callback) {
// var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || function(fn) { return window.setTimeout(fn, 20); };
var raf = function(fn) { return setTimeout(fn, 0); };
return raf(callback);
}
return {
add: addFunction,
force: forceProcessBatch
};
};
function Batch() {
var batch = {};
var size = 0;
var topLevel = 0;
var bottomLevel = 0;
function add(level, fn) {
if(!fn) {
fn = level;
level = 0;
}
if(level > topLevel) {
topLevel = level;
} else if(level < bottomLevel) {
bottomLevel = level;
}
if(!batch[level]) {
batch[level] = [];
}
batch[level].push(fn);
size++;
}
function process() {
for(var level = bottomLevel; level <= topLevel; level++) {
var fns = batch[level];
for(var i = 0; i < fns.length; i++) {
var fn = fns[i];
fn();
}
}
}
function getSize() {
return size;
}
return {
add: add,
process: process,
size: getSize
};
}