Skip to content

Instantly share code, notes, and snippets.

@mogsie
Last active January 9, 2018 23:00
Show Gist options
  • Save mogsie/79b6e5ddfc1b899065ea63bd6b348d5e to your computer and use it in GitHub Desktop.
Save mogsie/79b6e5ddfc1b899065ea63bd6b348d5e to your computer and use it in GitHub Desktop.
Wraps the xstate instance and a "current state". The transition function deals with calling side effects too.
class StateMachine {
constructor(machine, object) {
this.machine = machine;
this.object = object;
this.state = null;
this.timers = {}
}
event(event) {
const maybeNextState = ! this.state ? this.machine.initialState : this.machine.transition(this.state, event);
if (maybeNextState) {
this.state = maybeNextState;
if (this.state.actions) {
this.state.actions.filter(item => item.startsWith("cancel ")).forEach(item => this.timer(item));
this.state.actions.filter(item => item.startsWith("after ")).forEach(item => this.timer(item));
this.state.actions
.filter(item => !item.startsWith("cancel "))
.filter(item => !item.startsWith("after "))
.forEach(item => this.object[item]());
}
}
}
timer(args) {
args = args.split(" ");
if (args[0] == "after") {
this.timers[args[2]] = setTimeout(() => {
this.event(args[2]);
delete this.timers[args[3]];
}, parseFloat(args[1]) * 1000);
}
else if (args[0] == "cancel") {
const timer = this.timers[args[1]];
if (timer) {
clearTimeout(timer);
}
}
}
}
// Example state machine usage
{
state: {
on : {
search : "searching",
TIMEOUT : "searching",
change : "initial"
},
onEntry: "after 2.0 TIMEOUT",
onExit: "cancel TIMEOUT"
}
}
// example usage
// Where we are in our state machine
this.stateMachine = new StateMachine(statechart, this);
this.stateMachine.event();// ensure the initial state is entered, and any side effects of it happen.
this.stateMachine.event('change');
this.stateMachine.event('search');
@mogsie
Copy link
Author

mogsie commented Jan 8, 2018

I haven't thought much about what it should return, if anything. I'm firmly in the "fire and forget" camp when it comes to this. Maybe it could return true/false depending on if the transition actually fired an event, i.e sm.transition('OOPS') === false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment