“This is the 11th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”

So before we learn about finite state machines, we need to understand what a finite state machine is.

A finite state machine is a very useful model that can simulate a mathematical model of most things in the world. Being in one of a finite number of states at any one time. You can transition from one state to another in response to some external input.

Finite state machines have three characteristics:

  • The total number of states is finite.
  • I’m only in one state at any one time.
  • Under certain conditions, there is a transition from one state to another.

In JS, create an object, use the attributes of the object to simulate the state of the element, and use the method of the object to simulate the transformation of the element in different states. So this object is a finite state machine. Whether or not it can be described by a state machine depends on the current state. There are a finite number of states that respond to events and change regularly from one state to another. Promise is a finite state machine.

Finite state machines need to meet the required state determination, there are events to trigger the transition state, the total state is finite and the transition is regular. Such as switches, drop-down menus, in-game life and death states, etc.

Today we learn about state machines through an open source project.

javascript-state-machine

Finite state hangar.

In a browser:

<script src='state-machine.js'></script>

after downloading the source or the minified version

Using npm:

npm install --save-dev javascript-state-machine

In Node.js:

var StateMachine = require('javascript-state-machine');

A state machine can be constructed using:

var fsm = new StateMachine({
    init: 'solid',
    transitions: [
      { name: 'melt',     from: 'solid',  to: 'liquid' },
      { name: 'freeze',   from: 'liquid', to: 'solid'  },
      { name: 'vaporize', from: 'liquid', to: 'gas'    },
      { name: 'condense', from: 'gas',    to: 'liquid' }
    ],
    methods: {
      onMelt:     function() { console.log('I melted')    },
      onFreeze:   function() { console.log('I froze')     },
      onVaporize: function() { console.log('I vaporized') },
      onCondense: function() { console.log('I condensed') }
    }
  });
Copy the code

Above is an example given by the author.

Today we use traffic lights to learn about the project.

let StateMachine = require('javascript-state-machine') var fsm = new StateMachine({ init: 'red', transitions: [ { name: 'through', from: 'red', to: 'green' }, { name: 'slow', from: 'green', to: 'yellow' }, { name: 'stop', from: 'yellow', to: 'red'}], methods: {onThrough: function () {console.log(' green ', 'green ')}, onSlow: Function () {console.log(' yellow light please notice ')}, onStop: function () {console.log(' red light please wait ')},}})Copy the code

. It creates an object with the current state attribute:

Init: indicates the initial state value, which in our example is red.

An error is reported if the initial value does not exist

The FSM. State command is used to obtain the current status

console.log(fsm.state) // red
Copy the code

. Methods to transition to another state:

The transformation can be made by calling name

console.log(fsm.state); // red
fsm.through()
console.log(fsm.state); // green
Copy the code

However, if you print it, you’ll see “Green light please go” between red and green, because when you do the transition, you call onThrough, on, and remember name starts with a capital letter.

But if our current state value is red, we must proceed to the next state in order

console.log(fsm.state); Red fsm.slow() throw new Exception("transition is invalid in current state", transition, from, to, this.state); ^ { message: 'transition is invalid in current state', transition: 'slow', from: 'red', to: undefined, current: 'red' }Copy the code

By default, the state machine will throw an exception if you try to trigger a transition that is not allowed in the current state. If you want to handle the problem yourself, you can define a custom onInvalidTransition handler:

methods:{
	onInvalidTransition: function (transition, from, to) {
      console.error("transition not allowed from that state");
   },
}

console.log(fsm.state); // red
fsm.slow()
// transition not allowed from that state
Copy the code

StateMachine also provides the following helper methods:

  • Fsm. is(s) – Returns true if state S is the current state

  • Fsm.can (t) – Returns true if conversion t can occur from the current state

  • FSM. Cannot (t) – Returns true if conversion t cannot occur from the current state

  • Fsm.transitions () – Returns a list of transitions allowed in the current state

  • Fsm.alltransitions () – Returns a list of all possible transitions

  • Fsm.allstates () – Returns a list of all possible states

    console.log(fsm.is(‘red’)); // true console.log(fsm.can(‘through’)); // tr console.log(fsm.cannot(‘slow’)); // true console.log(fsm.transitions()); // [ ‘through’ ] console.log(fsm.allTransitions()); // [ ‘init’, ‘through’, ‘slow’, ‘stop’ ] console.log(fsm.allStates()); // [ ‘none’, ‘red’, ‘green’, ‘yellow’ ]

This is the basic function of the library, but it can also have other extensions:

  • States and Transitions
  • Data and Methods
  • Lifecycle Events
  • Asynchronous Transitions
  • Initialization
  • Error Handling
  • State History
  • Visualization
  • State Machine Factory
  • Upgrading from 2.x

That’s all FOR today, and we’ll talk about some more advanced features next time.