blob: 36380d5ea8d5e24ec713d8243f6269a86834ebed [file] [log] [blame]
// jWorkflow.js
// (c) 2010 tinyHippos inc.
// jWorkflow is freely distributable under the terms of the MIT license.
// Portions of jWorkflow are inspired by Underscore.js
var jWorkflow = (function () {
function _valid(func) {
if (typeof(func) !== 'function') {
throw "expected function but was " + typeof(func);
}
}
function _isWorkflow(func) {
return typeof func.andThen === 'function' &&
typeof func.start === 'function' &&
typeof func.chill === 'function';
}
function _isArray(func) {
return !!func.map && !!func.reduce;
}
var transfunctioner = {
order: function (func, context) {
var _workflow = [],
_tasks,
_callback = null,
_baton = (function () {
var _taken = false;
return {
take: function () {
_taken = true;
},
pass: function (result) {
var task;
_taken = false;
if (_tasks.length) {
task = _tasks.shift();
result = task.func.apply(task.context, [result, _baton]);
if (!_taken) {
_baton.pass(result);
}
}
else {
if (_callback.func) {
_callback.func.apply(_callback.context, [result]);
}
}
},
drop: function (result) {
_taken = true;
_tasks = [];
setTimeout(function () {
_baton.pass(result);
}, 1);
}
};
}()),
_self = {
andThen: function (func, context) {
if (_isWorkflow(func)) {
var f = function (prev, baton) {
baton.take();
func.start({
callback: function (result) {
baton.pass(result);
},
context: context,
initialValue: prev
});
};
_workflow.push({func: f, context: context});
}
else if (_isArray(func)) {
var orch = function (prev, baton) {
baton.take();
var l = func.length,
join = function () {
return --l || baton.pass();
};
func.forEach(function (f) {
jWorkflow.order(f).start(join);
});
};
_workflow.push({func: orch, context: context});
}
else {
_valid(func);
_workflow.push({func: func, context: context});
}
return _self;
},
chill: function (time) {
return _self.andThen(function (prev, baton) {
baton.take();
setTimeout(function () {
baton.pass(prev);
}, time);
});
},
start: function () {
var callback,
context,
initialValue;
if (arguments[0] && typeof arguments[0] === 'object') {
callback = arguments[0].callback;
context = arguments[0].context;
initialValue = arguments[0].initialValue;
}
else {
callback = arguments[0];
context = arguments[1];
}
_callback = {func: callback, context: context};
_tasks = _workflow.slice();
_baton.pass(initialValue);
}
};
return func ? _self.andThen(func, context) : _self;
}
};
return transfunctioner;
}());
if (typeof module === "object" && typeof require === "function") {
module.exports = jWorkflow;
}