Skip to content

Instantly share code, notes, and snippets.

@marcsolanadal
Last active August 23, 2018 08:06
Show Gist options
  • Save marcsolanadal/d6876c3b3e61c9939da84469c1febd06 to your computer and use it in GitHub Desktop.
Save marcsolanadal/d6876c3b3e61c9939da84469c1febd06 to your computer and use it in GitHub Desktop.
/**
* STATE PATTERN
*
* The State object:
* - Determines the transition to the next state.
* - Changes the current state in the state machine
*/
function trafficLight() {
const State = Object.freeze({
'GREEN': 'green',
'YELLOW': 'yellow',
'RED': 'red'
})
return {
initialState: State.GREEN,
states: {
[State.GREEN]: async function green(next) {
return await setTimeout(() => next(State.YELLOW), 2000)
},
[State.YELLOW]: async function yellow(next) {
return await setTimeout(() => next(State.RED), 500)
},
[State.RED]: async function red(next) {
return await setTimeout(() => next(State.GREEN), 2000)
}
}
}
}
function bouncer () {
const State = Object.freeze({
'ONE': 'one',
'DELAY': 'delay',
'TWO': 'two'
})
return {
initialState: State.ONE,
states: {
[State.ONE]: function one(next, counter = 0) {
if (counter < 4) {
next(State.ONE, counter += 1)
} else {
next(State.DELAY, State.TWO)
}
},
[State.DELAY]: async function delay(next, state) {
return await setTimeout(() => next(state), 2000)
},
[State.TWO]: function two(next, counter = 0) {
if (counter < 4) {
next(State.TWO, counter += 1)
} else {
next(State.DELAY, State.ONE)
}
}
}
}
}
function StateMachine({ initialState, states}) {
let currentState = initialState;
async function next(nextState, ...rest) {
if (typeof nextState !== 'undefined') {
currentState = nextState
console.log(`state changed to ${currentState}...`)
await states[currentState](next, ...rest)
}
}
next(currentState)
}
StateMachine(trafficLight())
StateMachine(bouncer())
@marcsolanadal
Copy link
Author

I provably should have mounting and dismounting logic in each state.

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