class MicroMachine {
This is a small Finite State Machine implementation in JavaScript.
class MicroMachine {
const MicroMachine = require('micromachinejs');
const initialState = 'unsubmitted';
const fsm = new MicroMachine(initialState);
constructor(initialState = 'initial') {
this.state = initialState;
this.events = {};
this.callbacks = {};
}
fsm
.when('submit', {
unsubmitted: 'submitted',
reverted: 'submitted',
})
.when('revert', { submitted: 'reverted' })
.when('approve', { submitted: 'approved' });
when(eventName, events = {}) {
this.events[eventName] = events;
return this;
}
fsm
.on('submit', (event) => {
// event.to
// event.from
// event.eventName
})
.on('submit', (event) => {
// multiple callbacks to same event are possible
})
.on('revert', (event) => {
// do something else
})
.on('any', (event) => {
// do something when any event is triggered
});
on(eventName, callback) {
if (!callback) { return this; }
const handlers = this.getCallbacks(eventName);
handlers.push(callback);
this.callbacks[eventName] = handlers;
return this;
}
fsm.off('submit') // remove 'submit' event callbacks
fsm.off() // remove all event callbacks
off(eventName) {
if (eventName) {
this.callbacks[eventName] = [];
} else {
this.callbacks = {};
}
return this;
}
fsm.trigger('submit'); // true
fsm.state; // "submitted"
trigger(eventName) {
if (this.canTriggerEvent(eventName)) {
const from = this.state;
const to = this.events[eventName][this.state];
this.triggerCallbacks(eventName, from, to);
this.state = to;
return true;
}
return false;
}
Return an Array
of all events.
getEvents() {
return Object.values(this.events);
}
Return an Array
of available events.
getAvailableEvents() {
const eventNames = Object.keys(this.events);
return eventNames.filter(eventName => this.canTriggerEvent(eventName));
}
Can event be triggered? Return a Boolean
.
canTriggerEvent(eventName) {
const events = this.events[eventName] || {};
return Object.prototype.hasOwnProperty.call(events, this.state);
}
Return a unique set (Array
) of all states.
getStates() {
let states = [];
this.getEvents().forEach((event) => {
const statesToAdd = Object.keys(event).concat(Object.values(event));
states = states.concat(statesToAdd);
});
return Array.from(new Set(states));
}
Return an Array
of callback functions for an event.
getCallbacks(eventName) {
return this.callbacks[eventName] || [];
}
Loop through each callback function and call it. Pass each function an event object:
{from: String, to: String, eventName: String}
triggerCallbacks(eventName, from, to) {
const callbacks = this.getCallbacks(eventName).concat(this.getCallbacks('any'));
callbacks.forEach((callback) => {
callback({ from, to, eventName });
});
}
}
module.exports = MicroMachine;