Skip to content
Nikhil Motiani edited this page Apr 12, 2019 · 2 revisions

Creating a Hierarchy

Both machina.Fsm and machina.BehavioralFsm instances support hierarchical relationships. Any state object under the states property can be given a _child member, which can be one of the following:

  • an actual FSM instance
  • a function which returns an FSM instance
  • an object with a factory method, which returns an FSM instance

Here's an example of two of these approaches:

var crosswalk = new machina.Fsm( {
    namespace: "crosswalk",
    initialState: "vehiclesEnabled",
    states: {
        vehiclesEnabled: {
            _onEnter: function() {
                this.emit( "pedestrians", { status: DO_NOT_WALK } );
            },
            timeout: "pedestriansEnabled",
            _child: vehicleSignal, // already-existing FSM instance
        },
        pedestriansEnabled: {
            _onEnter: function() {
                this.emit( "vehicles", { status: RED } );
            },
            timeout: "vehiclesEnabled",
            // factory function which returns an instance of an FSM
            _child: function() {
                return new PedestrianSignalFsm();
            }
        }
    }
} );

How Hierarchies Work

  • Input fed to the parent is passed to a child FSM (if one exists). If the child has a handler for the input, it handles it and any events emitted are bubbled up to the parent FSM and emitted from there (except for nohandler events).
  • If the child FSM does not have a handler for the input, it emits a nohandler event (just like any FSM normally would). The parent will detect this event and attempt to handle the input instead. If it doesn't have a handler, it will emit a nohandler event as well.
  • If input originates at a child FSM (e.g. - through a setTimeout call set up in the child), and the child does not have a handler for that input, it will bubble up to the parent to be handled there. (The parent will not attempt to delegate bubbled input back to the child that bubbled it up to begin with.)
  • Whenever the parent FSM transitions to a new state, if the new state has a child FSM, it's told to handle a _reset input just after the new state's _onEnter (if one exists) has completed execution.