Skip to content

Instantly share code, notes, and snippets.

@ne-sachirou
Last active December 18, 2015 12:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ne-sachirou/5780843 to your computer and use it in GitHub Desktop.
Save ne-sachirou/5780843 to your computer and use it in GitHub Desktop.
Minimal async flow controller. Like uupaa's Flow.js https://github.com/uupaa/flow.js
java -jar _resources/compiler.jar --compilation_level SIMPLE_OPTIMIZATIONS --language_in ECMASCRIPT5 --js public/javascripts/Flow.js --js_output_file public/javascripts/Flow.min.js
<script src="Flow.js"></script>
<script>
/**
* @param {boolean=} is_missable =false
* @return {Flow}
*/
function genFlow(is_missable) {
return new Flow(2,
function(err, passes) {
if (err)
console.log(err.message);
else
console.log(passes);
},
is_missable);
}
// pass() test.
var flow1 = genFlow();
setTimeout(function() {
flow1.pass('1 pass1!');
}, Math.floor(Math.random() * 5000));
setTimeout(function() {
flow1.pass('1 pass2!');
}, Math.floor(Math.random() * 5000));
setTimeout(function() {
flow1.pass('1 pass3!');
}, Math.floor(Math.random() * 5000));
// miss() test.
var flow2 = genFlow();
setTimeout(function() {
flow2.miss(new Error('2 miss1!'));
}, Math.floor(Math.random() * 5000));
setTimeout(function() {
flow2.miss(new Error('2 miss2!'));
}, Math.floor(Math.random() * 5000));
// is_missable test.
var flow3 = genFlow(true);
setTimeout(function() {
flow3.miss(new Error('3 miss1!'));
}, Math.floor(Math.random() * 5000));
setTimeout(function() {
flow3.pass('3 pass2!');
}, Math.floor(Math.random() * 5000));
// pass(, key) test.
var flow4 = genFlow();
setTimeout(function() {
flow4.pass('4 pass1!', 'key1');
}, Math.floor(Math.random() * 5000));
setTimeout(function() {
flow4.pass('4 pass2!', 'key2');
}, Math.floor(Math.random() * 5000));
</script>
/**
* @description Minimal async flow controller. Like uupaa's Flow.js https://github.com/uupaa/flow.js
* @author ne_Sachirou <utakata.c4se@gmail.com>
* @license Public Domain
*/
(function(scope) {
'use strict';
/**
* @constructor
* @param {number} waits
* @param {function(?Error,?Array.<Object>)} callback callback(err, passes)
* @param {boolean=} isMissable =false
*/
function Flow(waits, callback, isMissable) {
this.waits = waits;
this.callback = callback;
this.isMissable = !! isMissable;
/* @type {boolean} */
this.isFinished = false;
/* @type {Array.<Object>} */
this.passes = [ ];
Flow.flows.push(this);
}
/** @type {Array.<Flow>} */
Flow.flows = [ ];
/**
* @param {Object} value
* @param {string=} key
* @return {Flow}
*/
Flow.prototype.pass = function(value, key) {
if (this.isFinished) { return; }
if (key) {
this.passes[key] = value;
} else {
this.passes.push(value);
}
check(this);
return this;
};
/**
* @param {Error} err
* @return {Flow}
*/
Flow.prototype.miss = function(err) {
if (this.isFinished) { return; }
if (! this.isMissable) {
finalize(this);
this.callback(err, null);
} else {
check(this);
}
return this;
};
function check(flow) {
flow.waits -= 1;
if (flow.waits <= 0) {
finalize(flow);
flow.callback(null, flow.passes);
}
}
function finalize(flow) {
flow.isFinished = true;
Flow.flows = Flow.flows.filter(function(elm) { return elm !== flow; });
}
if (module) {
module.exports = Flow;
} else {
scope.Flow = Flow;
}
}(this.self || global));
/*
Public Domain
*/
(function(e){function b(a,f,c){this.waits=a;this.callback=f;this.is_missable=!!c;this.is_finished=!1;this.passes=[];b.flows.push(this)}function c(a){a.waits-=1;0>=a.waits&&(d(a),a.callback(null,a.passes))}function d(a){a.is_finished=!0;b.flows=b.flows.filter(function(b){return b!==a})}e.Flow=b;b.flows=[];b.prototype={pass:function(a,b){if(!this.is_finished)return b?this.passes[b]=a:this.passes.push(a),c(this),this},miss:function(a){if(!this.is_finished)return this.is_missable?c(this):(d(this),this.callback(a,
null)),this}}})(this);
// nodeunit test.
'use strict';
var Flow = require('../..').Flow;
exports.testFlowWorks = function(test) {
var flow;
test.expect(3);
flow = new Flow(2, function(error, passes) {
test.ok(! error);
test.equal(passes.length, 2);
test.ok(passes.some(function(v) { return v === 42; }) &&
passes.some(function(v) { return v === 8128; }) );
test.done();
});
setImmediate(function() { flow.pass(42); });
setImmediate(function() { flow.pass(8128); });
};
exports.testFlowMissWorks = function(test) {
var flow;
test.expect(1);
flow = new Flow(2, function(error) {
test.equal(error, 8128);
test.done();
});
setImmediate(function() { flow.pass(42); });
setImmediate(function() { flow.miss(8128); });
};
exports.testMissableDosentThrowError = function(test) {
var flow;
test.expect(2);
flow = new Flow(2, function(error, passes) {
test.ok(! error);
test.deepEqual(passes, [42]);
test.done();
}, true);
setImmediate(function() { flow.pass(42); });
setImmediate(function() { flow.miss(8128); });
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment