Javascript with finite state machine details

  • 2020-03-30 02:53:55
  • OfStack

In short, it has three characteristics:


*  Total number of states ( state ) is finite. 
*  At any one time, in only one state. 
*  Under certain conditions, it will change from one state ( transition ) to another state. 

What this means for JavaScript is that many objects can be written as finite state machines.

For example, there is a menu element on a web page. When the mouse hover, the menu is displayed; When the mouse is moved away, the menu is hidden. If a finite state machine is used to describe a menu with only two states (show and hide), the mouse will initiate a state transition.

The code can be written as follows:


var menu = {

    //The current state
    currentState: 'hide',

    //The binding event
    initialize: function() {
      var self = this;
      self.on("hover", self.transition);
    },

    //State transition
    transition: function(event){
      switch(this.currentState) {
        case "hide":
          this.currentState = 'show';
          doSomething();
          break;
        case "show":
          this.currentState = 'hide';
          doSomething();
          break;
        default:
          console.log('Invalid State!');
          break;
      }
    }

  };

As you can see, the finite state machine is written in a logical and expressive way, which is good for encapsulating events. The more states an object has and the more events that occur, the more suitable it is to write as a finite state machine.

In addition, JavaScript is a language with a lot of asynchronous operations, and the common solution is to specify callback functions, which can cause code structure confusion, difficult testing, and debugging problems. Finite state machines offer a better solution: hook an asynchronous operation to an object's state change, and when the asynchronous operation ends, the corresponding state change occurs, which triggers other operations. This makes more logical sense and reduces the complexity of the code than solutions like callback functions, event listening, publish/subscribe, etc.

The following is a function library for a Finite State Machine called Javascript Finite State Machine. This library is very easy to understand, can help us deepen the understanding, and the function is not weak at all.

The library provides a global object, StateMachine, whose create method can be used to generate instances of finite state machines.


var fsm = StateMachine.create();

When generated, you need to provide a parameter object that describes the nature of the instance. For example, traffic lights (traffic lights) can be described as follows:


var fsm = StateMachine.create({

initial: 'green',

events: [
{ name: 'warn',  from: 'green',  to: 'yellow' },
{ name: 'stop', from: 'yellow', to: 'red' },
{ name: 'ready',  from: 'red',    to: 'yellow' },
{ name: 'go', from: 'yellow', to: 'green' }
]
});

The initial state of a traffic signal is green, and the events property is a variety of events that trigger the state change, such as the warn event that makes the green state change to the yellow state, the stop event that makes the yellow state change to the red state, and so on.

After the instance is generated, you can query the current state at any time.


* fsm.current  : returns the current status. 
* fsm.is(s)  : returns a Boolean value representing the status s Is the current state. 
* fsm.can(e)  : returns a Boolean value representing the event e Whether it can be triggered in the current state. 
* fsm.cannot(e)  : returns a Boolean value representing the event e Cannot fire in the current state. 

Javascript Finite State Machine allows two callback functions to be specified for each event, with the warn event as an example:


* onbeforewarn In: warn Triggered before the event occurs. 
* onafterwarn Can be abbreviated as onwarn )   In: warn Triggered after the event. 

It also allows you to specify two callbacks for each state. Take the green state as an example:


* onleavegreen  : in the left green Triggered while in state. 
* onentergreen Can be abbreviated as ongreen )   : in the green Triggered while in state. 

Given that the warn event causes the state to change from green to yellow, the above four types of callback functions occur in the following order: onbeforewarn - onleavegreen - onenteryellow - onafterwarn.

In addition to specifying callbacks separately for each event and state, you can specify generic callbacks for all events and states.


* onbeforeevent  : triggered before any event occurs. 
* onleavestate  : triggered when leaving any state. 
* onenterstate  : triggered when entering any state. 
* onafterevent  : triggered after the end of any event. 


fsm.onwarn = function(){
light.fadeOut('slow', function() {
fsm.transition();
});
return StateMachine.ASYNC;
};

Javascript Finite State Machine also allows you to specify error handling functions that are automatically triggered when an event occurs that is impossible in the current State.


var fsm = StateMachine.create({
// ...
error: function(eventName, from, to, args, errorCode, errorMessage) {
return 'event ' + eventName + ': ' + errorMessage;
},
// ... 
});

For example, if the current state is green, then theoretically only a warn event can occur. If a stop event occurs, the above error handler is triggered.


Related articles: