How to let the on() callback be called for the startState?
On startup of my program, I need to be able to sync my state machine to an external/remote machine with the same states. Looking at the code, creating a new instance with the same startState seems to be the obvious way to do this. The problem now is that I also need the on() callback be called for that startState, which of course is not possible at the construction time of the FSM as the transitions are defined only after instantiation.
The reset() method unfortunately does not call the callbacks. Calling .go(startState) is only possible with allowImplicitSelfTransition=true, which is not an option for my case.
Am I missing something, or is this not possible at the moment?
I've thought of the following ways to achieve this functionality, but they all have some drawbacks or are not possible at all:
- maintaining my own mapping of on()-callbacks-functions and states outside the FSM, and then call the corresponding function for startState after initialization.
- introducing a special initial-start-state for every state in my FSM, with only a transition to the desired state, so that .go(desiredStartState) would be possible.
- subclassing the FSM and adding a method start(), which would look like
public start() {
const originalAllowImplicitSelfTransition = this._allowImplicitSelfTransition;
this._allowImplicitSelfTransition = true;
this.go(this._startState);
this._allowImplicitSelfTransition = originalAllowImplicitSelfTransition;
}
which would only work if both fields were protected, not private.
I think my favorite solution would be to have an extra parameter on reset(), like
public reset(execCallbacks = false).
I could try to make a PR for this, if it is a desirable solution.
What do you think?
Hi @bbjay please do make a PR
Just to be clear is the goal just to re-run the start state on() handlers on reset()? If so I think your proposed solution works. I agree we'll want it to be off by default to avoid a breaking change for other folks.
I might suggest a slightly different signature using an option bag just to give us room to grow any more flags in the future without having to grow a parameter list.
export interface ResetOptions {
runCallbacks?: boolean;
};
export const DefaultResetOptions: ResetOptions = {
runCallbacks: false
};
public reset(options?: ResetOptions) {
// if option is set override defaults, otherwise defaults
options = options ? { ...DefaultResetOptions, ...options } : { ...DefaultResetOptions };
} ;
Hi @eonarheim , yes exactly. Ok, will try that out on Sunday.