Last active
January 9, 2018 23:00
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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