State.js provides a flexible, feature-rich state machine implementation based on UML 2 state machines with blistering performance at runtime and minimal overheads.
Each language implementation of the state libraries has a public API that is designed to work with the language rather than being just a port from another language. As an example, the performance of state.js is achieved through pre-calculating and caching the internal method calls for transition traversal in arrays of functions at initialisation.
Documentation for the public API can be found here.
15 minutes of fame
state.js was featured on O'Reilly Radar in December 2013.
Why state machines?
State machines are a powerful tool to manage an objects behaviour under complex circumstances; they are especially well suited to environments where multiple sources of events can influence an object's behaviour.
State machines react to events based the state they are currently in and the event itself. Actions are performed when entering and exiting states and during the transitions between states.
Built for node.js
The addition of state machines with node.js provides a powerful controller framework for communication protocols and the lifecycle of objects within a node server.
State.js is available as a node packaged module.
States are the fundamental building block of a state machine; they represent a condition or situation during the life of an object. A state machine is built from states with transitions between them.
States can be: simple; composite, in which case they contain child states and pseudo states; orthogonal, in which case they contain child regions.
Final States are a special kind of state without any outbound transitions; reaching a final state means the parent region or composite state is ‘complete’.
In state.js, regions or composite states can be used as the top-level for a state machine.
Pseudo States are transient states within the state machine graph; pseudo states will always exit immediately after they’ve been entered. Pseudo States help structure a state machine.
In state.js, there are a number of different kinds of pseudo states, each with different behaviour: Choice, Deep History, Initial, Junction, Shallow History, and Terminate.
An Initial Pseudo State is typically used as the starting state of a region or composite state.
Transitions define the possible paths between states within a state machine graph. Transitions are triggered by and event and are followed if the [optionally] defined guard condition is met.
Completion transitions are a special kind of transition that are evaluated automatically after entering a state (these are mainly used as the outbound transitions from pseudo states, but can also be used from regular states).
Regions are the heart of any state machine; they contains the states and transitions forming a state machine graph.
In state.js, regions are commonly used as the top-level for a state machine.
Actions are where you define the behaviour associated with a state machine. Actions may be called when entering and exiting states as well as during the transitions between states.
The region and state classes along with the transition classes may be sub-classed and certain capabilities overridden.
Example 1. Cassette player controller
The following example shows a controller for a cassette player; the play, pause and stop buttons control the player's head and motor; take a look at the source of this page to see the state machine code. The 'flip' button just demonstrates history; when flipping back to the operational state, the last known child state is restored.
Press the buttons below to send events to the controller:
Sample code (the code that runs the example above)
Example 2. HTML Tabs
The tabs used throughout the Steelbreeze website are controlled using a simple state machine, where each tab is a state whose entry action reveals the tab page and colours the tab and exit action does the reverse. Check out tabs.js.
Open source licensing
Steelbreeze is a strong supporter of open source software; the open source licence is an appropriate option if you are creating an open source application under a licence compatible with MIT. Steelbreeze uses the MIT licence as it provides flexibility and protection for both the author and users of open source software.
A commercial licence is required if you wish to have commercial level support for state.js. Pricing for the licence will vary based on the the nature of the software you are developing and its distribution.