ifandelse / machina.js

js ex machina - finite state machines in JavaScript
http://machina-js.org/
Other
1.93k stars 147 forks source link

Problem with this statements using machina with node v4.1.1 #128

Closed edwinallenz closed 8 years ago

edwinallenz commented 8 years ago

I'm learning how to use machina. I reproduced the sample on the Readme, with the following code. https://gist.github.com/edwinallenz/0a1d5417079a78f5b2f9f2e3e78c20b4

I have problems with the this statements inside the states Any help will be apreciated

ifandelse commented 8 years ago

@edwinallenz In the gist, you're using ES6 arrow functions. Arrow functions use a lexical this, so the this value inside, for example, the uninitialized state's * handler isn't the FSM instance, it's the scope in which you set the arrow functions up. You'll need to use regular functions, as these are methods on the FSM instance that need to access the FSM instance as this. Most of these methods can get away with ES6 object shorthand as well. For example:

const Machina = require ( "./lib/machina" );

const vSignal = new Machina.Fsm( {
    initialize( options ) { },
    namespace: "vehicle-signal",
    initialState: "uninitialized",
    states:{
        uninitialized:{
            "*": function() {
                this.deferUntilTransition();
                this.transition( "green" );
            }
        },
        green:{
            _onEnter() {
                this.timer = setTimeout( () => {
                    this.handle( "timeout" );
                }, 3000 );
                this.emit( "vehicles", { status: "GEEN" } );
            }, 
            timeout:"green-interruptible",
            pedestrianWaiting() {
                this.deferUntilTransition( "green-interruptible" );
            },
            _onExit() {
                clearTimeout( this.timer );
            }
        },
        "green-interruptible":{
            pedestrianWaiting: "yellow"
        },
        yellow: {
            _onEnter() {
                this.timer = setTimeout( () => {
                    this.handle( "timeout" );
                }, 1000 );
                this.emit( "vehicles", { status: "RED" } );
            },
            _reset: "green",
            _onExit() {
                clearTimeout( this.timer );
            }
        }
    },
    reset() {
        this.handle( "_reset" );
    },
    pedestrianWaiting(){
        this.handle( "pedestrianWaiting" );
    }
})

console.dir( vSignal );
vSignal.pedestrianWaiting();

vSignal.on( "transition", ( data ) => {
     console.log( "we just transitioned from " + data.fromState + " to " + data.toState );
} );

vSignal.on( "*", ( eventName, data ) => {
    console.log( "this thing happened:", eventName );
} );

I'd also caution you against using _ in place of () when you're creating an arrow function that either takes no args, or has args you don't care about. You run the risk of variable shadowing, since lodash is typically in scope if you're using machina's API, and it's module value is assigned to _.

edwinallenz commented 8 years ago

Thanks for clarifying :smile: