Skip to content

razic/state-machine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

State Machine

Event-driven finite-state machine.

Dr. Seuss Machine

Installation

component install razic/state-machine

API

StateMachine(object)

The 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:

var StateMachine = require("state-machine");
var stateMachine = new StateMachine();

stateMachine.state = "off";
stateMachine.events = {
  push: [
    { from: ["off"], to: "on" },
    { from: ["on"], to: "off" }
  ]
};

As a mixin:

var StateMachine = require("state-machine");
var button = {
  state: "off",
  events: {
    push: [
      { from: ["on"], to: "off" },
      { from: ["off"], to: "on" }
    ]
  }
};

StateMachine(button);

As a prototype mixin:

var StateMachine = require("state-machine");
var Button = function() {};

Button.prototype.state = "off";
Button.prototype.events = {
  push: [
    { from: ["off"], to: "on" },
    { from: ["on"], to: "off" }
  ]
};

StateMachine(Button.prototype);

StateMachine#on(event, fn)

Register an event handler fn.

StateMachine#can(event)

Returns true or false if the event can transition.

StateMachine#transition(fn)

Transitions the state appropriately then calls fn passing two arguments, the from and to states.

StateMachine#event(...)

Where #event is one of the declared events. These methods get dynamically created after setting the events property.

Example

A good example is a turnstile. Here is what the state diagram looks like:

Turnstile state diagram

var StateMachine = require('state-machine');

function Turnstile() {}

Turnstile.prototype.state = "locked"; // This is your initial state
Turnstile.prototype.pushes = 0;
Turnstile.prototype.coins = 0;

// Define the events
Turnstile.prototype.events = {
  push: [{ from: ["unlocked"], to: "locked" }],
  coin: [{ from: ["locked", "unlocked"], to: "unlocked" }]
};

// Mixin the prototype
StateMachine(Turnstile.prototype);

// Declare the "push" event behavior
Turnstile.prototype.on("push", function() {
  this.transition(function() {
    this.pushes += 1;
  });
});

// Declare the "coin" event behavior
Turnstile.prototype.on("coin", function() {
  this.transition(function() {
    this.coins += 1;
  });
});

// Create your object
var turnstile = new Turnstile();

// Play with it
turnstile.state;       // Returns "locked"
turnstile.can("push"); // Returns false
turnstile.can("coin"); // Returns true
turnstile.push();      // Emits the "push" event
turnstile.state;       // Returns "locked"
turnstile.can("push"); // Returns false
turnstile.can("coin"); // Returns true
turnstile.coin();      // Emits the "coin" event
turnstile.state;       // Returns "unlocked"
turnstile.can("coin"); // Returns true
turnstile.can("push"); // Returns true
turnstile.coin();      // Emits the "coin" event
turnstile.state;       // Returns "unlocked"
turnstile.can("coin"); // Returns true
turnstile.can("push"); // Returns true
turnstile.push();      // Emits the "push" event
turnstile.state;       // Returns "locked"
turnstile.can("coin"); // Returns true
turnstile.can("push"); // Returns false
turnstile.coins        // Returns 2
turnstile.pushes       // Returns 1

License

MIT

About

Event-driven finite-state machine.

Resources

Stars

Watchers

Forks

Packages

No packages published