• Jump To … +
    impulse.js pipeline.js arsenal.js binding.js event.js functional.js grid.js sequence.js throttle.js trigger.js
  • pipeline.js

  • ¶

    Pipeline Mechanism

    Stablity: DEPRECATED

    CAVEAT: This mechanism is deprecated, and will be removed at version 2.0.0

    Requires: Event, Functional

    A functional pipeline mechanism, by utilizing the Event and Functional mechanism.

    (function (Arsenal) {
    
        var Event = Arsenal.Event;
  • ¶

    Use node's built-in Event instead if available

        if (Arsenal.node) {
            Event = require("events").EventEmitter;
        }
  • ¶

    Pipeline module

    • Constructor

      ```var pipeline = new Arsenal.Pipeline()*

        function Pipeline(options) {
    
            /* Inherits with Event mechanism */
            Event.call(this);
    
            /* Initialize options */
            this._options = Arsenal.extend({
                consistent: true
            }, options || {});
    
            /* Initialize variables */
            this._flows = {};
    
        }
  • ¶
    • pipeline.create(name, definition)

      Create a new flow in the pipeline

      Parameters:

      • name string Flow name

      • definition function Flow definition function

        Returns:

      • boolean Whether the flow is loaded successfully

        The flow definition function accepts one parameter uses as the Functional mechanism:

        function (F) { ... }

        function create(name, definition) {
    
            return this.load(new Flow(name, definition));
    
        }
  • ¶
    • pipeline.load(flow)

      Load the specified flow into pipeline

      Parameters:

      • flow Flow|Array|object This parameter can be in 3 types:

        • Flow The flow instance of Pipeline.Flow

        • Array An array of flow instances

        • object Object map with key/value: name => definition

        Returns:

      • boolean Whether the flow is loaded successfully

        function load(flow) {
    
            var result, i;
    
            /* Multiple flows in an array (elements in flow instance) */
            if (Arsenal.isArray(flow)) {
                result = true;
    
                for (i = 0; i < flow.length; i++) {
                    result = result && this.load(flow[i]);
                }
    
                return result;
    
            /* Multiple flows via object map (name => definition) */
            } else if (Arsenal.isHash(flow)) {
                result = true;
    
                for (i in flow) {
                    result = result && this.create(i, flow[i]);
                }
    
                return result;
            }
    
            /* Single flow */
            if (! (flow instanceof Flow)) {
                return false;
            }
    
            var flowName = flow.name();
    
            /* Unload existed flow first */
            this.unload(flowName);
    
            /* Handle flow events */
            flow.on("done", this.doneHandler.bind(this));
            flow.on("trouble", this.troubleHandler.bind(this));
    
            this._flows[flowName] = flow;
    
            return true;
    
        }
  • ¶
    • pipeline.unload(name)

      Unload the specific flow from pipeline and return back

      Parameters:

      • name string Name of the flow to be unloaded

        Returns:

      • Flow The unloaded flow object instance of Pipeline.Flow

        function unload(name) {
    
            var flow = this._flows[name];
    
            if (this._flows[name]) {
                this._flows[name].removeAllListeners("done");
                this._flows[name].removeAllListeners("trouble");
    
                delete this._flows[name];
            }
    
            return flow;
    
        }
  • ¶
    • pipeline.clear()

      Remove all loaded flows

        function clear() {
    
            var keys = Arsenal.getKeys(this._flows);
    
            for (var i = 0; i < keys; i++) {
                this.unload(keys[i]);
            }
    
        }
  • ¶
    • pipeline.check()

      Check for the existance of the specified flow

      Parameters:

      • name string Flow name to be checked
        function check(name) {
    
            return Arsenal.isObject(this._flows[name]) &&
                this._flows[name] instanceof Pipeline.Flow;
    
        }
  • ¶
    • pipeline.get(name, [args], [context], [callback])

      Get entry function of the specific flow

      Parameters:

      • name string Flow name

      • args Array Arguments pass to the flow entry

      • context object Context object of the flow

      • callback function Callback function to be called after the flow completed

        Returns:

      • function The entry function of the flow, or null when the flow has no functions

        function get(name, args, context, callback) {
    
            var flow = this._flows[name];
    
            if (! flow) {
                throw new ReferenceError("Flow not found: " + name);
            }
    
            /* Initialize flow context */
            if (! Arsenal.isObject(context)) {
                context = {
                    _stack: [],
                    _checkpoints: []
                };
            }
    
            /* Set up callback stack and checkpoints */
            if (! Arsenal.isArray(context._stack)) {
                context._stack = [];
            }
    
            if (! Arsenal.isArray(context._checkpoints)) {
                context._checkpoints = [];
            }
    
            if (Arsenal.isFunction(callback)) {
                context._stack.push(callback);
            }
    
            return flow.entry(args, context);
    
        }
  • ¶
    • pipeline.run(name, [args], [context], [callback])

      Run the specified flow

      Parameters:

      • name string Flow name

      • args Array Arguments pass to the flow entry

      • context object Context object of the flow

      • callback function Callback function to be called after the flow has finished

        Returns:

      • ANY Return value of the flow entry

        function run(name, args, context, callback) {
    
            var r = this.get(name, args, context, callback);
    
            if (! r) {
                throw new ReferenceError("Flow is empty: " + name);
            }
    
            return r.apply(null, args);
    
        }
  • ¶
    • Event done

      Emit when the flow has done successfully

      Listener pattern: function (name, result)

      Parameters for listeners:

      • name string Flow name

      • result ANY Flow result

        function doneHandler(snapshot, result) {
    
            var context = snapshot.context;
    
            this.emit("done", context._name, result);
  • ¶

    Clean up checkpoints

            if (context._checkpoints) {
                var checkpoint = context._checkpoints.pop();
    
                if (context._stack) {
                    if (checkpoint < context._stack.length) {
                        context._checkpoints.push(checkpoint);
                    }
    
                } else {
                    context._checkpoints = [];
                }
            }
  • ¶

    Continue to next callback from the stack

            if (context._stack) {
                var callback = context._stack.pop();
    
                if (Arsenal.isFunction(callback)) {
                    callback(result);
                }
            }
    
        }
  • ¶
    • Event error

      Emit when the required flow is not found

      Listener pattern: function (name, snapshot)

      Parameters for listeners:

      • snapshot object Current snapshot
        function troubleHandler(snapshot) {
    
            var context = snapshot.context;
    
            if (! this._flows[snapshot.name]) {
                this.emit("error", context._name, snapshot);
    
            } else {
                var consistent = this._options.consistent,
                    newContext = {
                        _name: snapshot.name,
                        _stack: [],
                        _checkpoints: []
                    },
                    checkpoint = -1;
    
                if (! Arsenal.isArray(context._stack)) {
                    context._stack = [];
                }
    
                if (! Arsenal.isArray(context._checkpoints)) {
                    context._checkpoints = [];
                }
  • ¶

    Option: context consistent

                if (consistent) {
                    newContext = context;
                }
  • ¶

    Stack checkpoint processing --

                if (snapshot.nested && snapshot.callback) {
                    checkpoint = context._stack.length;
    
                } else if (context._checkpoints.length > 0) {
                    checkpoint = context._checkpoints.pop();
    
                    if (checkpoint === context._stack.length) {
  • ¶

    Rewrite nested mark

                        snapshot.nested = true;
    
                    } else if (checkpoint < context._stack.length) {
  • ¶

    Push checkpoint back

                        context._checkpoints.push(checkpoint);
                    }
    
                    checkpoint = -1;
                }
    
                if (snapshot.nested || consistent) {
  • ¶

    Inherit checkpoints

                    newContext._checkpoints = context._checkpoints;
    
                } else {
                    newContext._checkpoints = [];
                }
    
                if (checkpoint !== -1 &&
                    newContext._checkpoints.indexOf(checkpoint) === -1) {
  • ¶

    Save checkpoint

                    newContext._checkpoints.push(checkpoint);
                }
  • ¶

    --

    Callback stack processing --

                if (snapshot.nested || consistent) {
  • ¶

    Clone the stack

                    newContext._stack = context._stack;
    
                } else {
                    newContext._stack = [];
                }
    
                if (Arsenal.isFunction(snapshot.callback)) {
                    newContext._stack.push(snapshot.callback);
                }
  • ¶

    --

                this.run(snapshot.name, snapshot.args, newContext);
            }
    
        }
    
        /* Inherits with Event mechanism */
        Arsenal.extend(Pipeline.prototype, Event.prototype);
  • ¶

    Primary functions

        Pipeline.prototype.create = create;
        Pipeline.prototype.load = load;
        Pipeline.prototype.unload = unload;
        Pipeline.prototype.clear = clear;
        Pipeline.prototype.check = check;
        Pipeline.prototype.get = get;
        Pipeline.prototype.run = run;
        Pipeline.prototype.doneHandler = doneHandler;
        Pipeline.prototype.troubleHandler = troubleHandler;
  • ¶

    Statical functions

    • Pipeline.createFlow(name, definition)

      Create a new flow, individually

      Parameters:

      • name string Flow name

      • definition function Flow definition function

        The flow definition function accepts one parameter uses as the Functional mechanism:

        function (F) { ... }

        function createFlow(name, definition) {
    
            return new Flow(name, definition);
    
        }
    
        Pipeline.createFlow = createFlow;
  • ¶

    Flow Mechanism

    The event-driven wrapper for the Functional mechanism

        var Flow = (function (Arsenal) {
  • ¶
    • Constructor

      Create a new flow instance

        ```var flow = new Flow(name, definition)```

      NOTICE: For production, use Pipeline to create flow

      Parameters:

      • name string Flow name

      • definition function Flow definition function

        The flow definition function accepts one parameter uses as the Functional mechanism:

        function (F) { ... }

            function Flow(name, definition) {
    
                /* Inherits with Event mechanism */
                Event.call(this);
    
                if (! name) {
                    throw new Error("Flow name cannot be empty");
                }
    
                this._name = name;
                this._entry = null;
                this._functional = new Arsenal.Functional(this.hook.bind(this));
    
                if (Arsenal.isFunction(definition)) {
                    definition(this._functional);
                }
    
            }
  • ¶
    • flow.hook(err, snapshot, result)

      The hook callback for Functional mechanism

      Parameters:

      • err Error or null null or Error object when required function was not found

      • snapshot object The snapshot of the Functional mechanism

      • result ANY Return value of the function, or undefined when an error occurs

            function hook(err, snapshot, result) {
    
                if (err) {
                    /* Redirect to other flow */
                    this.emit("trouble", snapshot);
    
                } else {
                    /* Done with current flow */
                    this.emit("done", snapshot, result);
                }
    
            }
  • ¶
    • flow.name(name)

      Get/set name of the flow

      Parameters:

      • name string Flow name

        Returns:

      • string Name of the flow

            function name(name) {
    
                if (name) {
                    this._name = name;
                }
    
                return this._name;
    
            }
  • ¶
    • flow.entry([args], [context], [callback])

      Get entry function of the flow

      Parameters:

      • args Array Arguments pass to the flow entry

      • context object Context object of the flow

      • callback function Callback function to be called after the flow has finished

        Returns:

      • function The entry function of the flow, or null when the flow has no functions

            function entry(args, context, callback) {
    
                var entry = this._entry,
                    f = this._functional;
    
                /* Check for flow entry */
                if (! entry) {
                    var keys = Arsenal.getKeys(f());
    
                    if (keys.length > 0) {
                        entry = keys[0];
    
                    } else {
                        /* Empty flow */
                        return null;
                    }
                }
    
                /* Initialize flow arguments */
                if (! Arsenal.isArray(args)) {
                    args = [];
                }
    
                /* Store flow name in the context */
                if (! Arsenal.isObject(context)) {
                    context = { _name: this._name };
    
                } else {
                    context._name = this._name;
                }
    
                return f(entry, args, context, callback);
    
            }
  • ¶
    • flow.run([args], [context], [callback])

      Run flow from the entry

      Parameters:

      • name string Flow name

      • args Array Arguments pass to the flow entry

      • context object Context object of the flow

      • callback function Callback function to be called after the flow has finished

        Returns:

      • ANY Return value of the flow entry

            function run(args, context, callback) {
    
                var r = this.entry(args, context, callback);
    
                if (r) {
                    return r.apply(null, args);
    
                } else {
                    return null;
                }
    
            }
    
            /* Inherits with Event mechanism */
            Arsenal.extend(Flow.prototype, Event.prototype);
  • ¶

    Primary functions

            Flow.prototype.hook = hook;
            Flow.prototype.name = name;
            Flow.prototype.entry = entry;
            Flow.prototype.run = run;
    
            return Flow;
    
        })(Arsenal);
        /* /Flow */
    
        Pipeline.Flow = Flow;
    
        /* Export the Pipeline mechanism */
        Arsenal.Pipeline = Pipeline;
        return Pipeline;
    
    })(this);