Simply put, it has three characteristics:
The code copy is as follows:
* The total number of states (state) is limited.
* At any moment, you are only in one state.
* Under certain conditions, it will transition from one state to another.
What it means for JavaScript is that many objects can be written as finite state machines.
For example, there is a menu element on the web page. When the mouse is hovering, the menu is displayed; when the mouse is moved away, the menu is hidden. If you use the finite state machine description, this menu has only two states (show and hide), and the mouse will trigger a state transition.
The code can be written as follows:
The code copy is as follows:
var menu = {
// Current status
currentState: 'hide',
// Binding events
initialize: function() {
var self = this;
self.on("hover", self.transition);
},
// Status 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;
}
}
};
It can be seen that the writing method of finite state machines is clear in logic and strong in expression, which is conducive to encapsulating events. The more states an object has and the more events it occurs, the more suitable it is to use the finite state machine writing method.
In addition, JavaScript is a language with a lot of asynchronous operations. The commonly used solution is to specify callback functions, but this will cause problems such as confusing code structure, difficult to test and debugging. The finite state machine provides a better way: hook asynchronous operations with the state change of the object. When the asynchronous operation is completed, a corresponding state change occurs, thereby triggering other operations. This is more logically reasonable than the solution of callback functions, event listening, publish/subscribe, etc., and is easier to reduce the complexity of the code.
The following is a finite state machine library, Javascript Finite State Machine. This library is very easy to understand and can help us deepen our understanding, and its functions are not weak at all.
This library provides a global object StateMachine, which uses the create method of the object to generate instances of a finite state machine.
The code copy is as follows:
var fsm = StateMachine.create();
When generating, a parameter object needs to be provided to describe the properties of the instance. For example, traffic lights (traffic lights) can be described as follows:
The code copy is 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 the traffic light is green. The events attribute is various events that trigger state changes, such as the warning event that causes the green state to become yellow state, the stop event causes the yellow state to become red state, etc.
After generating the instance, you can query the current status at any time.
The code copy is as follows:
* fsm.current: Returns the current status.
* fsm.is(s): Returns a Boolean value indicating whether state s is the current state.
* fsm.can(e): Returns a Boolean value indicating whether event e can be triggered in the current state.
* fsm.cannot(e): Returns a boolean value indicating whether event e cannot be triggered in the current state.
Javascript Finite State Machine allows specifying two callback functions for each event, taking the warning event as an example:
The code copy is as follows:
* onbeforewarn: Triggered before the warning event occurs.
* onafterwarn (can be abbreviated as onwarn): Triggered after the warn event occurs.
At the same time, it also allows specifying two callback functions for each state, taking the green state as an example:
The code copy is as follows:
* onleavegreen: Triggered when leaving the green state.
* onentergreen (can be abbreviated as ongreen): Triggered when entering the green state.
Assuming that the warn event changes the state from green to yellow, the above four types of callback functions occur in the following order: onbeforewarn → onleavegreen → onenteryellow → onafterwarn.
In addition to specifying a callback function for each event and state separately, you can also specify a common callback function for all events and states.
The code copy is as follows:
* onbeforeevent: Triggered before any event occurs.
* onleavestate: Triggered when leaving any state.
* onenterstate: Triggered when entering any state.
* onafterevent: Triggered after either event ends.
If there are asynchronous operations in the callback function of the event (such as Ajax communication with the server), we may want to wait until the asynchronous operation is over before the state changes occur. This requires the transition method.
The code copy is as follows:
fsm.onwarn = function(){
light.fadeOut('slow', function() {
fsm.transition();
});
return StateMachine.ASYNC;
};
In the callback function in the above code, there is an asynchronous operation (light.fadeOut). If you do not want the state to change immediately, you must let the callback function return a StateMachine.ASYNC object, indicating that the state does not change for the time being; wait until the asynchronous operation is completed, then call the transition method to cause the state to change.
Javascript Finite State Machine also allows specifying error handling functions that are automatically triggered when events that are impossible to occur in the current state.
The code copy is as follows:
var fsm = StateMachine.create({
// ...
error: function(eventName, from, to, args, errorCode, errorMessage) {
return 'event ' + eventName + ': ' + errorMessage;
},
// ...
});
For example, the current state is green, and theoretically, only a warning event may occur at this time. If a stop event occurs at this time, the above error handling function will be triggered.