fsmjs

State machines are back

fsmjs

State machines are back, the async way!

$ npm install fsmjs
var fsmjs = require('../lib/fsmjs');
 
var tim = fsmjs({
 
    idle: {
 
        // when 'go' or 'start' or 'g' are pushed, we move to 'running' and start
        // an interval that emits a 'tick' event every 100ms.
        '(go|start|g)': function(cb) {
            process.stdout.write('starting engines...\n');
            tim.state = 'running'; 
            tim._timer = tim.interval('tick', 100);
            cb();
        },
 
        // strings are target states (and emitted events)
        exit: 'end',
        e: 'error',
 
        // any other event in this state shows this error
        '.*': function(cb, e) {
            console.log('error: i cant understand what you mean by "' + e + '"');
            cb();
        },
    },
 
    running: {
 
        // animate clock every tick
        tick: function(cb) {
            var clock = [ '|', '/', '-', '\\' ];
            process.stdout.write('(' + clock[tim._i] + ")");
            for (var i = 0; i < 50; ++i) process.stdout.write(' ');
            process.stdout.write('\r');
            tim._i = (tim._i + 1) % clock.length;
            cb();
        },
 
        // cannot exit from this state
        exit: 'error',
 
        // when 'no' or 'stop' or 'x' are pushed, move to 'stopping' and start
        // a 2sec timeout that emits 'elapsed' when elapsed (surpise!)
        '(no|stop|x)': function(cb) { 
            process.stdout.write('stopping...\n');
            tim.state = 'stopping';
            tim.timeout('stopped', 5000);
 
            cb();
        },
 
        $exit: function(cb) {
            // take some time before changing state.
            console.log('our running times are over.. give me 2 more seconds.');
            setTimeout(cb, 2000);
        },
 
    },
 
    stopping: {
 
        // called when the stopping timer elapses. clears the 
        // interval and changes state to 'idle'
        stopped: function(cb) {
            process.stdout.write('\nall done.\n');
            clearInterval(tim._timer);
            tim.state = 'idle';
            cb();
        },
 
        // a tick during stop operation, show dots
        tick: function(cb) {
            process.stdout.write(".");
            cb();
        },
 
        exit: 'error',
 
    },
 
    error: function(cb, state) {
        console.log('An error occured in state', state);
        tim.state = state;
        cb();
    },
 
    _timer: null, // timer object to allow clearing the interval
    _i: 0, // animated clock
});
 
tim.on('end', function() {
    process.exit();
});
 
tim.on('error', function() {
    console.log('on-error');
});
 
tim.on('idle.start', function() {
    console.log("try 'go' the next time...");
});
 
var i = require('../lib/debugger')(tim, { verbose: false });

More examples under examples/.