@thomasrandolph/fsm
v0.0.6
Published
### Start quick
Downloads
10
Maintainers
Readme
fsm
Start quick
import { Machine } from "@thomasrandolph/fsm";
var fsm = new Machine( {
"initial": "idle",
"states": {
"idle": {
"on": {
"LOAD": "pending"
}
},
"pending": {
"on": {
"LOADED": "idle"
}
}
}
} );
fsm.subscribe( ( state ) => {
console.log( state );
} );
fsm.send( "LOAD" );
console.log( fsm.state );
fsm.send( "LOADED" );
console.log( fsm.state );
/*
Logs:
- "pending"
- "pending"
- "idle"
- "idle"
*/Context
The state machine can hold data for you so that your state can be associated with arbitrary values.
var fsm = new Machine( {
"initial": "idle",
"states": {
"idle": {}
},
"context": {
"clicks": 0
}
} );
console.log( fsm.context ); // Logs `{ "clicks": 0 }`Note that the context getter returns a frozen structuredClone of the internal context object. It is - effectively - a read-only snapshot. structuredClones also cannot contain non-serializable values (like a Function). Including these types of values in your context will result in an Error being thrown when accessing the context getter.
Entry & Exit Actions
You can provide an enter and exit handler for any of your finite states.
The enter and exit action handlers are called with the current state and the current context as their arguments. enter is triggered after switching to the new state, and exit is triggered before leaving the current state.
var fsm = new Machine( {
"initial": "idle",
"states": {
"idle": {
"on": {
"LOAD": "pending"
},
"enter": ( state, context ) => ({ ...context, "requests": context.requests - 1 }),
"exit": ( state, context ) => ({ ...context, "clicks": context.clicks + 1 })
},
"pending": {
"on": {
"LOADED": "idle"
},
"enter": ( state, context ) => ({ ...context, "requests": context.requests + 1 })
}
},
"context": {
"clicks": 0,
"requests": 0
}
} );
console.log( fsm.context );
fsm.send( "LOAD" );
console.log( fsm.context );
fsm.send( "LOADED" );
console.log( fsm.context );
/*
Logs:
- { "clicks": 0, "requests": 0 }
- { "clicks": 1, "requests": 1 }
- { "clicks": 1, "requests": 0 }
*/If the enter or exit action handlers modify the context, it must be returned from the action to be saved on the machine. If a falsey value is returned, the original context is restored to the machine.
If you have no need to modify the context of the machine (or don't use that feature), just omit the action handler return altogether.
Subscribing
You can subscribe to state changes from the machine with .subscribe( callback ).
callback is called after any enter action and is provided the current state and context as its arguments.
.subscribe returns a function that unsubscribes from the machine.
var fsm = new Machine( {
"initial": "idle",
"states": {
"idle": {
"on": {
"LOAD": "pending"
}
},
"pending": {
"on": {
"LOADED": "idle"
}
}
}
} );
var unsubscribe = fsm.subscribe( ( state, context ) => {
console.log( state, context );
} );
fsm.send( "LOAD" );
// Logs: "pending" {}
unsubscribe();
fsm.send( "LOADED" );
// No output