Event-driven finite-state machine.
component install razic/state-machineThe StateMachine can be used as a mixin. For example, a "plain" object may also
become a state machine, or you may extend an existing prototype.
As a StateMachine instance:
varStateMachine=require("state-machine");varstateMachine=newStateMachine();stateMachine.state="off";stateMachine.events={push: [{from: ["off"],to: "on"},{from: ["on"],to: "off"}]};As a mixin:
varStateMachine=require("state-machine");varbutton={state: "off",events: {push: [{from: ["on"],to: "off"},{from: ["off"],to: "on"}]}};StateMachine(button);As a prototype mixin:
varStateMachine=require("state-machine");varButton=function(){};Button.prototype.state="off";Button.prototype.events={push: [{from: ["off"],to: "on"},{from: ["on"],to: "off"}]};StateMachine(Button.prototype);Register an event handler fn.
Returns true or false if the event can transition.
Transitions the state appropriately then calls fn passing two arguments, the
from and to states.
Where #event is one of the declared events. These methods get dynamically
created after setting the events property.
A good example is a turnstile. Here is what the state diagram looks like:
varStateMachine=require('state-machine');functionTurnstile(){}Turnstile.prototype.state="locked";// This is your initial stateTurnstile.prototype.pushes=0;Turnstile.prototype.coins=0;// Define the eventsTurnstile.prototype.events={push: [{from: ["unlocked"],to: "locked"}],coin: [{from: ["locked","unlocked"],to: "unlocked"}]};// Mixin the prototypeStateMachine(Turnstile.prototype);// Declare the "push" event behaviorTurnstile.prototype.on("push",function(){this.transition(function(){this.pushes+=1;});});// Declare the "coin" event behaviorTurnstile.prototype.on("coin",function(){this.transition(function(){this.coins+=1;});});// Create your objectvarturnstile=newTurnstile();// Play with itturnstile.state;// Returns "locked"turnstile.can("push");// Returns falseturnstile.can("coin");// Returns trueturnstile.push();// Emits the "push" eventturnstile.state;// Returns "locked"turnstile.can("push");// Returns falseturnstile.can("coin");// Returns trueturnstile.coin();// Emits the "coin" eventturnstile.state;// Returns "unlocked"turnstile.can("coin");// Returns trueturnstile.can("push");// Returns trueturnstile.coin();// Emits the "coin" eventturnstile.state;// Returns "unlocked"turnstile.can("coin");// Returns trueturnstile.can("push");// Returns trueturnstile.push();// Emits the "push" eventturnstile.state;// Returns "locked"turnstile.can("coin");// Returns trueturnstile.can("push");// Returns falseturnstile.coins// Returns 2turnstile.pushes// Returns 1MIT