Posted at

Flow.js: 最小限の非同期処理コントローラJavaScript

More than 5 years have passed since last update.

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


Flow.min.js

/*

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


Flow.js

/**

* @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記:さっちゃんですよ☆