deep-package-manager
Version:
DEEP Package Manager
200 lines (161 loc) • 3.57 kB
JavaScript
/**
* Created by AlexanderC on 6/3/15.
*/
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.WaitFor = undefined;
var _InvalidArgumentException = require('../Exception/InvalidArgumentException');
/**
* Wait for something
*/
class WaitFor {
constructor() {
this._stack = [];
this._toSkip = [];
this._children = [];
}
/**
* @returns {Number}
*/
get childrenCount() {
return this._children.length;
}
/**
* @returns {Array}
*/
get children() {
return this._children;
}
/**
*
* @param {Function} executor
* @param {Function} cb
* @param {Array[]} series
*/
static waterfall(executor, cb, ...series) {
let wait = new WaitFor();
let args = series.shift();
if (!Array.isArray(args)) {
args = [args];
}
let readyCb = executor(...args);
wait.push(readyCb);
wait.ready(() => {
if (series.length > 0) {
WaitFor.waterfall(executor, cb, ...series);
return;
}
cb();
});
}
/**
* @param {WaitFor|null} child
* @returns {WaitFor}
*/
addChild(child = null) {
child = child || new WaitFor();
if (!(child instanceof WaitFor)) {
throw new _InvalidArgumentException.InvalidArgumentException(child, WaitFor);
}
this._children.push(child);
return this;
}
/**
* @param {Number} index
* @returns {WaitFor}
*/
child(index) {
if (this.childrenCount < index) {
throw new _InvalidArgumentException.InvalidArgumentException(index, 'existing index');
}
return this._children[index];
}
/**
* @returns {Number}
*/
get count() {
return this._stack.length;
}
/**
* @returns {Number}
*/
get remaining() {
return this._stack.length - this._toSkip.length;
}
/**
* @param {Function} condition
* @returns {WaitFor}
*/
push(condition) {
if (!(condition instanceof Function)) {
throw new _InvalidArgumentException.InvalidArgumentException(condition, 'Function');
}
this._stack.push(condition);
return this;
}
/**
* @param {Function} callback
*/
ready(callback) {
if (!(callback instanceof Function)) {
throw new _InvalidArgumentException.InvalidArgumentException(callback, 'Function');
}
let skipStack = [];
for (let i = 0; i < this.count; i++) {
let condition = this._stack[i];
if (condition()) {
this._toSkip.push(condition);
skipStack.push(i);
}
}
for (let i in skipStack) {
if (!skipStack.hasOwnProperty(i)) {
continue;
}
delete this._stack[skipStack[i]];
}
if (this.remaining > 0) {
setTimeout(() => {
this.ready(callback);
}, WaitFor.TICK_TTL);
} else {
this._readyChildren(callback, 0);
}
}
/**
* @param {Function} callback
* @param {Number} level
*/
_readyChildren(callback, level) {
let remaining = this._children.length - level;
if (remaining <= 0) {
callback();
return;
}
let subWait = new WaitFor();
for (let i in this._children) {
if (!this._children.hasOwnProperty(i)) {
continue;
}
this._children[i].ready(() => {
remaining--;
});
level++;
}
subWait.push(() => {
return remaining <= 0;
});
subWait.ready(() => {
this._readyChildren(callback, level + 1);
});
}
/**
* @returns {Number}
*/
static get TICK_TTL() {
return 100;
}
}
exports.WaitFor = WaitFor;