-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathStateMachine.js
49 lines (37 loc) · 1.46 KB
/
StateMachine.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
export default function(startState, onError) {
const stateFns = {}
function start(model, config = {}) {
const logging = config.logging === true
const machine = { state: null, model, setState, inState, dispatch }
function err(msg) {
if (onError) return onError(machine, msg)
throw Error(msg)
}
function inState() {
return !!Array.from(arguments).find(state => machine.state === state)
}
function dispatch(event, data) {
if (machine.state === null) err(`no start state set`)
if (logging) console.log(`dispatch: ${machine.state}:${event}`, data)
const events = stateFns[machine.state]
if (!events) err(`transition ${machine.state}:${event} not defined`)
const fn = stateFns[machine.state][event]
if (!fn) err(`transition ${machine.state}:${event} not defined`)
fn(machine, data)
}
function setState(state) {
if (logging) console.log(`transition: ${machine.state} -> ${state}`)
machine.state = state
}
setState(startState)
return machine
}
function transition(state, event, fn) {
if (!stateFns[state]) stateFns[state] = {}
if (stateFns[state][event]) {
throw new Error(`transition ${state}:${event} already defined`)
}
stateFns[state][event] = fn
}
return { start, transition }
}