uupaaさんのFlow.jsではなくて、其のFlow.jsの、minimalな機能を再實裝しました。練習以上の意味は有りません(〃l _ l)
See Gist 最小限の非同期処理コントローラJavaScript - c4se記:さっちゃんですよ☆.
API
var flow = new Flow(3, callback);
と、非同期に待つtaskの數と、callback函數を指定してFlowを生成します。taskは、成功したtimingでflow.pass(value);
を呼び出してあげてください。或るtaskが失敗した、或いは指定された個數のtaskが成功した時点で、callbackを呼びます。
var flow = new Flow(2,
function(err, passes) {
if (err)
throw err;
else
console.log(passes);
// -> ['pass! 1', 'pass! 2'] (順不同)
});
setTimeout(function() { flow.pass('pass! 1'); },
Math.floor(Math.random() * 5000));
setTimeout(function() { flow.pass('pass! 2'); },
Math.floor(Math.random() * 5000));
失敗した場合は、flow.miss(err);
を呼んでください。
setTimeout(function() { flow.miss(new Error('miss! 1')); },
Math.floor(Math.random() * 5000));
callbackの引數には
- 或るtaskが失敗した場合: errにはErrorが、passesにはnull
- 全てのtaskが成功した場合: errにはnullが、passesにはpass()に渡された値の配列
が渡されます。Maybeの様なものです。
flow.pass(value, key);
にはkeyを渡す事ができます。key附きのpass()とkey無しのpass()は、同時に使えます。
var flow = new Flow(3,
function(err, passes) {
if (err)
throw err;
else
console.log(passes);
// -> { 'first': 'pass!', 'second': 'pass!' } and passes[0] === 'pass! 3'
});
setTimeout(function() { flow.pass('pass!', 'first'); },
Math.floor(Math.random() * 5000));
setTimeout(function() { flow.pass('pass!', 'second'); },
Math.floor(Math.random() * 5000));
setTimeout(function() { flow.pass('pass! 3'); },
Math.floor(Math.random() * 5000));
失敗可能なFlowも定義できます。var Flow(num, callback, true);
と、is_missableにtrueを渡してください。flow.is_missable === true
であるFlowは、Errorがthrowされない限り決して失敗しません。
var flow = new Flow(2,
function(err, passes) {
console.log(passes);
}, true);
setTimeout(function() { flow.pass('pass! 1'); },
Math.floor(Math.random() * 5000));
setTimeout(function() { flow.miss(new Error('miss! 2')); },
Math.floor(Math.random() * 5000));
現在待ち中のFlowは、Flow.flows
にて一覧できます。
Minified
/*
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);
小さいでしょ(〃l _ l)☆
Main
/**
* @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) {
scope.Flow = Flow;
/**
* @constructor
* @param {number} waits
* @param {function(Error,Array.<Object>)} callback callback(err, passes)
* @param {boolean=} is_missable =false
*/
function Flow(waits, callback, is_missable) {
this.waits = waits;
this.callback = callback;
this.is_missable = !! is_missable;
/** @type {boolean} */
this.is_finished = false;
/** @type {Array.<Object>} */
this.passes = [];
Flow.flows.push(this);
}
/** @type {Array.<Flow>} */
Flow.flows = [];
Flow.prototype = {
/**
* @param {Object} value
* @param {string=} key
* @return {Flow}
*/
pass: function(value, key) {
if (this.is_finished)
return;
if (key)
this.passes[key] = value;
else
this.passes.push(value);
check(this);
return this;
},
/**
* @param {Error} err
* @return {Flow}
*/
miss: function(err) {
if (this.is_finished)
return;
if (! this.is_missable) {
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.is_finished = true;
Flow.flows = Flow.flows.filter(function(elm) { return elm !== flow; });
}
}(this));
codeは此ちらに → 最小限の非同期処理コントローラJavaScript - c4se記:さっちゃんですよ☆。