vstirbu/fsm-as-promised

Conditional branching

cstyan opened this issue · 6 comments

This seems like sort of a given for state machines, but I'm not seeing any documentation on how I might be able to do this with your library.

I have a state that has one from state and two to states, and based on some logic executed inside that state I need to be able to decide which of the to states to transition to. Is this currently possible?

I think that this situation can be achieved using an intermediate pseudo-state, like in this example:

StateMachine({
  events: [
    { name: 'trigger', from: 'existing', to: 'pseudo' },
    { name: 'triggerOptionA', from: 'pseudo', to: 'option-a' },
    { name: 'triggerOptionB', from: 'pseudo', to: 'option-b' }
  ],
  callbacks: {
    onenteredpseudo: function (opts) {
      if (condition) {
        this.triggerOptionA.apply(this, opts.args);
      } else {
        this.triggerOptionB.apply(this, opts.args);
      }
    }
  }
});

Does it suit your case or I got it wrong?

Yes, I think this might work. I'll try it out and let you know, thanks.

Basically my use case is that I'm sending a packet out and then waiting for the response. Based on the response (one of two possible responses) or a timeout, I want to transition to one of three states. This pseudo state looks like it will handle that well.

Sorry, I don't mean to use this issue as a support forum, but I have more questions and am not sure where is better to ask them. I'm having trouble figuring out how to actually use this module without examples. I've looked through the tests but I'm still a bit lost.

Is it possible for the entire state machine to be run in an automated way after calling the first event? So I have a few events on my object, and calling the first event will transition to the second, but after that it seems as if I have to then call the third event in order to transition from the second to the third. If I've defined the from and to for all my events should the execution just not continue?

Also, I understand the call order and locking for callbacks, but it seems like onleave{some event} is not called consistently?

My code is currently this:

let fsm = StateMachine({
  condition: 0,
  initial: "start",
  events: [
    { name: "waitForAuth", from: "start", to: "auth1" },
    { name: "auth1", from: "waitForAuth", to: "auth2" },
    { name: "auth2", from: "auth1", to: "connected" },
  ],
  callbacks: {
    onleavestart: function () {
      console.log("sent cnxn");
    },
    onwaitForAuth: function () {
      console.log("waiting for auth from device");
    },
    onleavewaitForAuth: function () {
      console.log("recv'd auth from device");
    },
    onenteredauth1: function () {
      console.log("waiting for auth response");
    },
    onauth1: function () {
      console.log("in auth 1");
    }
  }
});

And the output of calling fsm.start is:

sent cnxn
waiting for auth from device
waiting for auth response

So onleavewaitForAuth is never called.

Assuming that you triggered the transition from the startstate using fsm.waitForAuth the output is correct. Some of the confusion might be caused because you use the same name for states (e.g. the value of from and to) and events (e.g. the value of name).

You cannot transition from one state to another without triggering explicitly events. This hold even if you have guard conditions in the onentered{state}. You still have to call the event that will trigger the new transition.

Thanks for the clarification, obviously I misunderstood the formatting difference between states and transitions(events). Seems like I can get the functionality I need by triggering the next transition inside the onentered{someState} callbacks.

Thanks again.

Nice to see that the library suits your needs well!

I've added a section with recipes in the documentation containing conditional transitions (for now).