LoginSignup
2
2

More than 5 years have passed since last update.

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

Posted at

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

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2