Skip to content

Instantly share code, notes, and snippets.

@sundarj
Last active August 27, 2015 16:36
Show Gist options
  • Save sundarj/52d0defcf9c0b0df2c22 to your computer and use it in GitHub Desktop.
Save sundarj/52d0defcf9c0b0df2c22 to your computer and use it in GitHub Desktop.
JS State Machine
function Machine() {
this.states = [];
this.current = null;
this.verbose = false;
}
Machine.prototype.advance = function (input) {
function next(pass) {
this.current = this.states.filter(function (state) {
return state.name === this.current.to
}, this).pop();
this.advance(pass);
};
if (this.verbose)
console.log((this.current.to ? 'doing:' : 'finally:'), this.current.name);
this.current.action.call(this, input, next.bind(this));
};
Machine.prototype.define = function (states) {
this.states = this.states.concat(states);
return this;
};
Machine.prototype.add = function (states) {
states = [].concat(states);
states.forEach(function (state) {
var index;
this.states = this.states.map(function (st, ind) {
if (st.to === state.before) {
st.to = state.name;
index = ind;
state.to = state.before;
}
return st;
});
delete state.before;
this.states.splice(index, 0, state);
}, this);
return this;
}
Machine.prototype.begins = function (input) {
this.current = this.states[0];
this.advance(input);
};
var json = new Machine();
json.verbose = true;
json.define([
{
name: 'parse',
action: function (input, next) {
input.foo = 'not bar';
next(input);
},
to: 'stringify'
},
{
name: 'stringify',
action: function (input, next) {
next(JSON.stringify(input));
},
to: 'done'
},
{
name: 'done',
action: function (input) {
console.log(input);
}
}
]).begins({
foo: 'bar',
apple: 'orange'
});
json.add({
name: 'wrap',
before: 'done',
action: function (input, next) {
next('<em>' + input + '</em>');
}
}).begins({
foo: 'bar',
apple: 'orange'
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment