State Machine

A powerful yet simply-configured JavaScript finite-state machine

Overview

State Machine is a powerful yet simply-configured state machine.

Its intuitive (opens new window) yet (opens new window) powerful (opens new window) DSL can describe states and transitions succinctly whilst its JavaScript API (opens new window) hooks into transitions with a rich event syntax (opens new window) to build complex application flows (opens new window):

const transitions: [
    "warn  : green > yellow",
    "panic : green   yellow > red",
    "calm  :         yellow < red",
    "clear : green < yellow   red"
]

The interactive demo above shows-off many of StateMachine’s features. Visit the site itself (opens new window) and view the source code directly in the page, or open the console here to see the application log updates as it transitions between states and fires events.

Implementation

The library itself is built as a stand-alone library with two component parts:

  • the DSL lexer and parser
  • the state machine engine

The syntax of the library consists of the transition setup (text or object format) and optional handlers:

const config = {

  transitions: [
    'warn  : green > yellow',
    'panic : green   yellow > red',
    'calm  :         yellow < red',
    'clear : green < yellow   red',
  ],

  handlers: {
    'action:end': function (event) {
      console.info(event.transition)
    },
    'red:leave': function (event, fsm) {
      console.log(event)
      fsm.pause()
      setTimeout(function () {
        fsm.resume()
      }, 1000)
    },
  },

}

const fsm = new StateMachine(config)

The above is the classic traffic light (opens new window) example, with some additional handlers to show off the API.

The library can be used on its own (as per most of the examples) or with helpers to power jQuery (opens new window), Angular (opens new window) or Vue (opens new window).

Thoughts

I built State Machine after becoming interested in state machines as a potential solution to complex user flows such as checkouts or multi-step forms.

As it happens, I’ve never used it in production, and it’s just ended up as a cool technology investigation.

If I had the time and inclination to continue this project, the main aims would be:

  • decouple the notation DSL from the core library
  • add support for nested state machines

I would imagine these days if you wanted to use state machines, you would look at X State (opens new window). A fun next step for this library would be enabling the DSL to build state machines for that library.

So...

I hope you found this post interesting or inspiring.

If you want to engage further, follow me on Twitter or drop a comment or reaction below.

Either way, thanks for reading!