Skip to content

1.1. The Publish–Subscribe messaging system

Francisco Bernardo edited this page Dec 4, 2020 · 1 revision

The message-oriented subsystem enables self-contained components to communicate with each other without needing to depend on each other directly. This supports a cleaner architecture.

You can find the messaging implementation of a publish-subscribe or Observer pattern with a message protocol in sema/client/messaging/pubSub.js.

To use the messaging subsystem, you need to import PubSub, create a local instance, subscribe to or publish messages.

    import { PubSub } from '../messaging/pubSub.js';

    this.messaging = new PubSub();

To subscribe to messages by topic, we use a "lowercase-lowercase" format convention such as add-eval-dsp or stop-audio, and associate it with a local event handler function. For instance the audioEngine subscribes to all these messages:

    this.messaging.subscribe("eval-dsp", e => this.evalDSP(e));
    this.messaging.subscribe("stop-audio", e => this.stop());
    this.messaging.subscribe("load-sample", (name, url) =>
      this.loadSample(name, url)
    );
    this.messaging.subscribe("model-output-data", e =>
      this.onMessagingEventHandler(e)
    );
    this.messaging.subscribe("clock-phase", e =>
      this.onMessagingEventHandler(e)
    );
    this.messaging.subscribe("model-send-buffer", e =>
      this.onMessagingEventHandler(e)
    );
    this.messaging.subscribe("add-engine-analyser", e =>
      this.createAnalyser(e)
    );
    this.messaging.subscribe("remove-engine-analyser", e =>
      this.removeAnalyser(e)
    );

To publish messages with a specific topic, we use the same "lowercase-lowercase" format convention such as analyser-data, with a JSON object for payload. For instance, the audioEngine publishes analyser data for rendering in the Analyser widget.

const analyserPollingLoop = () => {
        analyserData = this.pollAnalyserData(analyser);

        this.messaging.publish("analyser-data", analyserData);

In turn, the Analyser widget, on load, both publishes and subscribes to the Audio engine using the messaging system

  import { PubSub } from '../../messaging/pubSub.js';

  let messaging = new PubSub()

  onMount(async () => {
    // Request the creation of a WAAPI analyser to the Audio Engine
    
    messaging.publish("add-engine-analyser", { id } );

    canvas.addEventListener('click', () => toggleRendering(), false);

    messaging.subscribe('analyser-data', e => updateAnalyserByteData(e) );

  });