Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to define input common to all states? #141

Closed
bedeho opened this issue Jun 13, 2017 · 3 comments
Closed

How to define input common to all states? #141

bedeho opened this issue Jun 13, 2017 · 3 comments

Comments

@bedeho
Copy link

bedeho commented Jun 13, 2017

  1. Very often, one will have input common to all states, but there seems to be no way to define this?
  2. Is it allowed to define an input for a state which is handled by a sub machine? so
...
states : {
 my_state : {
  _child: ...
  input_here: ... // <====
 }
}

Is this input_here allowed, and when will it be triggered?

@itoche
Copy link

itoche commented Jun 13, 2017

1/ I don't think there is a direct way to do it. On my side, I did it like this in the state machine initializer function:

initialize: function(options) {
              Object.keys(this.states).forEach((item) => {
                  this.states[item].reset = function(client) {
                      console.log('Resetting state machine...');
                      this.transition(client, "start");
               };;
});

2/ I think so. You 'input_here' will be called if your child state machine current state has no such input defined. Documentation mentions:

If a child FSM handles input that it does not have a handler for, it will bubble the input up to the parent FSM to be handled there.

@bedeho
Copy link
Author

bedeho commented Jun 13, 2017

Oh, that was clever! Thank you for the tip, will consider that!

@ifandelse
Copy link
Owner

@bedeho Apologies for the long delay in replying :) (see #146).

There actually is a shortcut way to implement a common handler for all states, though I highly recommend using it with caution, since I believe it's always better to explicitly declare what inputs each state handles. If you implement a method at the top of the FSM and then call fsm.handle( nameOfTheMethodYouAdded) where the current state doesn't have an explicit handler by that name, machina will look at the FSM's instance methods and if a matching one is found, it invokes it. For example:

const list = new machina.BehavioralFsm({
    namespace: "priorityTest",
    initialState: "ready",
    states: {
        ready: {
            next: "todo"
        },
        todo: {
            next: "doing"
        },
        doing: {
            next: "done"
        },
        done: {
            next() {
                console.log( "I already made the donuts...." );
            }
        }
    },
    next( client ) {
        this.handle(client, "next" );
    },
    altNext( client ) {
        this.handle( client, "next" );
    }
} );

In the above example, any of these three ways effectively feed a next input to the FSM:

let client = {};
list.next(client);
list.altNext(client);
list.handle(client, "next");

This also holds true for a top level catch-all *handler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants