DEV Community

francesco agati
francesco agati

Posted on

Simulating a Traffic Light with Bacon.js and state machine

Handling asynchronous events and managing state effectively are essential skills. Functional Reactive Programming (FRP) provides a powerful paradigm that simplifies these tasks by treating events as continuous streams of data.

Understanding the Traffic Light State Machine

Let's start by defining the states and transitions of our traffic light using a simple state machine approach:

const Bacon = require('baconjs');

// Define traffic light states and transitions
const trafficLightStateMachine = {
  initialState: 'Green',
  transitions: {
    'Green': { nextState: 'Yellow', duration: 3000 },
    'Yellow': { nextState: 'Red', duration: 1000 },
    'Red': { nextState: 'Green', duration: 2000 }
  }
};
Enter fullscreen mode Exit fullscreen mode

Here, the traffic light begins at 'Green', transitions to 'Yellow' after 3 seconds, then to 'Red' after 1 second, and finally back to 'Green' after another 2 seconds.

Simulating Traffic Light Events

To simulate the traffic light's behavior, we'll create a stream of events using Bacon.js:

const simulateTrafficLight = Bacon.fromArray([
  { type: 'state', value: 'Green' },
  { type: 'timeout' },
  { type: 'state', value: 'Yellow' },
  { type: 'timeout' },
  { type: 'state', value: 'Red' },
  { type: 'timeout' },
  { type: 'state', value: 'Green' },
  { type: 'timeout' }
]);
Enter fullscreen mode Exit fullscreen mode

This simulateTrafficLight stream alternates between emitting state change events ('state') and timeout events ('timeout'), mimicking the traffic light's transitions in a controlled manner.

Implementing the State Machine with withStateMachine

The heart of our simulation lies in using withStateMachine provided by Bacon.js. It allows us to model the traffic light's behavior based on the defined state machine:

simulateTrafficLight
  .withStateMachine(trafficLightStateMachine.initialState, function(state, event) {
    if (event.type === 'state') {
      // Emit the current state and schedule the next transition
      return [state, [{ type: 'timeout', delay: trafficLightStateMachine.transitions[state].duration }]];
    } else if (event.type === 'timeout') {
      // Transition to the next state
      const nextState = trafficLightStateMachine.transitions[state].nextState;
      return [nextState, [{ type: 'state', value: nextState }]];
    } else {
      // Pass through unknown events
      return [state, [event]];
    }
  })
  .log();
Enter fullscreen mode Exit fullscreen mode

In this setup:

  • When a 'state' event is encountered, it emits the current state and schedules the next transition after the specified duration.
  • When a 'timeout' event occurs, it transitions to the next state as defined in the state machine.
  • Any other events are passed through without changes.

Visualizing the Traffic Light Simulation

By logging the output of our state machine, we can observe the sequence of state changes and timeouts as they occur based on our predefined simulation:

simulateTrafficLight
  .withStateMachine(/*...*/)
  .log();
Enter fullscreen mode Exit fullscreen mode

Functional Reactive Programming with Bacon.js offers a straightforward yet powerful approach to managing state and handling events in JavaScript. By using FRP principles, you can build applications that are not only responsive but also easier to maintain and extend over time.

Mastering these concepts opens up possibilities for creating more interactive and dynamic web experiences. Whether you're building a traffic light simulator or handling real-time data updates, Bacon.js and FRP provide a solid foundation for modern JavaScript development.

In conclusion, diving into FRP with Bacon.js can elevate your JavaScript skills and empower you to tackle complex event-driven scenarios with confidence.

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more