-
• #2
Personally, if you're trying to do something async you might be better off writing your own state machine system from scratch.
However, I guess if you think about it, there's actually an intermediate state where you were in one state, you got the signal, and now you're waiting until the code completes async and you can move to the next state.
If you had state
1
and state2
, this could be state1_busy
:- In state 1
- Signal received : stuff happens, move to state 1_busy
- Stuff completes async, move to state2
So in that case I think you can do it with the current system. The handler for state 1 returns
1_busy
, and then it sends a signal to the FSM when it properly completes, which causes1_busy
to change to2
? - In state 1
-
• #3
Im am not completely sure, but there seems to be a simple solution with the already existing Espruino StateMachine module:
Why no do the actual asynchronous work in the "enter" function of each state, and then trigger a state transition in the last "then" block of the chained Promises as follows:
function enterOne() { console.log("Enter One..."); new Promise((resolve, reject) => { setTimeout(() => { resolve('good'); }, 5000); }) .then((result) => { sm.signal(result); }) .catch(() => { sm.signal('bad'); }); };
In the "signal" function of the respective state there could be code that decides - based on the parameter on the "signal" call (here: 'good' or 'bad') - to which new state to transition:
function signalOne(result, e) { console.log("signal one with parameters", result, e); if ('good' === result) { return {state:'Two', wait:(e)?e:0}; } else if ('bad' === result) { return {state:'Error', wait:(e)?e:0}; } };
I think this will fit my needs.
There is already a simple State Machine implementation in Espruino:
https://www.espruino.com/modules/StateMachine.js
State transitions are triggered by calling
However, this expects that the "signal" function of the respective current state synchronously executes some operations and then returns the information what should be the next state to transition to. But how can I handle it if the "signal" function does some asynchronous operations (based on chained Promises). In this case, I cannot immediately decide what the next state should be. I just could return nothing, but then there would be no state transition. I cannot "await" the chained Promises. Actually, I don't see a way to do the state transition at the end of the Promises chain.
Any clever ideas?
Update 2019-01-08 : After trying out different approaches I think I could emit events. So the state transitions would be somehow triggered by the receipt of events. And it is no problem to emit events in chained Promises.