state-machine-js v0.0.7
state-machine-js
Finite State Machine
A simple utility that allows you to define states and actions to transition between them.
Installation
- npm:
npm install state-machine-js --save-dev - bower:
bower install state-machine-js --save-dev
Usage
var stateMachine = new StateMachine();
var State = {
CLOSED: 'CLOSED',
OPENED: 'OPENED',
LOCKED: 'LOCKED'
};
var Action = {
CLOSE: 'CLOSE',
OPEN: 'OPEN',
LOCK: 'LOCK',
UNLOCK: 'UNLOCK'
};
var config = [
{
initial: true,
name: State.CLOSED,
transitions: [
{ action: Action.OPEN, target: State.OPENED },
{ action: Action.LOCK, target: State.LOCKED }
]
},
{
name: State.OPENED,
transitions: [
{ action: Action.CLOSE, target: State.CLOSED }
]
},
{
name: State.LOCKED,
transitions: [
{ action: Action.UNLOCK, target: State.CLOSED }
]
}
];
// create multiple states with a config array
stateMachine.create(config);
// add listener for state change
stateMachine.onChange.add(function(state, data, action) {
console.log('State has changed to:', state.name);
console.log('Got data:', data);
console.log('Got triggering action:', action);
});
// start
stateMachine.start(); // state changed to 'CLOSED' because that state has 'initial' flag
// state will change to 'LOCKED':
stateMachine.action(Action.LOCK);
// state won't change - no valid transition to 'CLOSED' from 'LOCKED':
stateMachine.action(Action.CLOSE);
// state will change to 'CLOSED', data payload sent through:
stateMachine.action(Action.UNLOCK, { foo: 'bar' });
// debug view with info and buttons to change state
var debugView = new StateMachine.DebugView(stateMachine);
document.body.appendChild(debugView);States can be created individually:
// create a single state
stateMachine.create({
name: State.LOCKED,
transitions: [
{ action: Action.UNLOCK, target: State.CLOSED }
]
});
// create multiple states by chaining
stateMachine.create({
name: State.LOCKED,
transitions: [
{ action: Action.UNLOCK, target: State.CLOSED }
]
}).create({
name: State.CLOSED,
transitions: [
{ action: Action.LOCK, target: State.LOCKED }
]
});You can add callbacks to receive notifications when the State Machine is entering or exiting a State and optionally cancel the transition:
// add listener for state enter
stateMachine.onEnter.add(function(state, data, action) {
console.log('State will change to:', state.name);
// unless:
if(someCondition) {
stateMachine.cancel(); // will not enter this State
}
});
// add listener for state exit
stateMachine.onExit.add(function(state, data, action) {
console.log('State will change from:', state.name);
// unless:
if(someCondition) {
stateMachine.cancel(); // will not exit this State
}
});You can also add optional callbacks to individual states:
// by retrieving individual states
var state = stateMachine.getState('LOCKED');
state.onEnter.add(function(state, data, action) {
// entering LOCKED State
// Possible to cancel transition in by calling stateMachine.cancel()
});
state.onChange.add(function(state, data, action) {
// in LOCKED State
});
state.onExit.add(function(state, data, action) {
// exiting LOCKED State
// Possible to cancel transition out by calling stateMachine.cancel()
});
// or via config object
stateMachine.create({
name: 'LOCKED',
transitions: [
{ action: 'UNLOCK', target: 'CLOSED' }
],
onEnter: function(state, data, action) {
// entering LOCKED state
// Possible to cancel transition in by calling stateMachine.cancel()
},
onChange: function(state, data, action) {
// in LOCKED state
},
onExit: function(state, data, action) {
// exiting LOCKED state
// Possible to cancel transition out by calling stateMachine.cancel()
}
});API
Methods
create(config)create new Statesstart() returns StateMachinestarts State Machine, transitioning to 'initial' Stateaction(action, data) returns StateMachineinitiates a State transitioncancel() returns StateMachinecancels the current transitiongetState(stateName) returns Stateretrieve a StateremoveState(stateName) returns Stateremove a StategetTotal() returns numbertotal number of States defined
Getters
currentState returns StatepreviousState returns Statestates returns Objectinitial returns Statethe initial Statehistory returns arrayarray of State names (strings)
Callbacks
onChange.add(callback, context)add callback when State has changedonEnter.add(callback, context)add callback when entering a StateonExit.add(callback, context)add callback when exiting a State
onChange.remove(callback, context)remove callbackonEnter.remove(callback, context)remove callbackonExit.remove(callback, context)remove callback
onChange.removeAll()remove all callbacksonEnter.removeAll()remove all callbacksonExit.removeAll()remove all callbacks
Dev Setup
To install dependencies:
$ bower installTo run tests:
$ npm install -g karma-cli
$ npm install
$ karma start