Event-Based Programming is natural to any GUI based interface. HTML DOM¹ offers an inbuilt Event Notification model, but it is only useful when dealing with DOM Elements. There is no support for non-DOM elements.
Web applications have grown in complexity with time; also, JavaScript started participating in backend applications, which in turn made the world see JavaScript as more than HTML DOM manipulation gig.
This article showcases building up a custom event publisher-subscriber model on top of Reactive Programming for non-DOM elements.
Event-Driven Programming
Event-Driven programming paradigm² introduces an intuitive flow of control based upon events.
Button is clicked => show dialog.
Vocabulary
In general, Publisher-Subscriber or PubSub term is used collectively for event publishers and even subscribers.
Reactive Programming
Reactive Programming paradigm² introduces the processing of streams of data asynchronously. It is a trending paradigm² these days.
RxJS is a reactive programming extension for JavaScript. You are going to build an event notification model on top of it by modelling events as a stream of data.
Problem Statement
Consider modelling Thermostat, when room temperature crosses a certain threshold (
30°C
), AC would turn up, and windows would close.Design
Consider class
Thermostat
which encapsulates the logic of monitoring and publishes events:Data Structure for holding event structure
RxJS offers
Subject
which can be used to emit events to multiple subscribers.class Thermostat {
constructor(sensor) {
// data structure for holding subscriptions
this.subscriptions = {
above: new Subject(),
below: new Subject()
};
}
}
Notice, there are two
Subject
objects. You can also create a single Subject
object named ThresholdCrossed
with direction above
or below
. Separating the event or combining the event is Design Concern, which may depend upon many factors.Subscription API for Event
on
API for registering action based upon event. Subject
offers subscribe
API which would be called whenever there is new data is available.on(event, action) {
// sanatize event .. left code
this.subscriptions[event].subscribe(v => action(v));
}
Publishing Events
Consider
monitor
method which detects the rise and falls in temperature and publishes event accordingly using next
API.monitor(currentTemperature) {
// when temperature cross above THRESHOLD
if (
currentTemperature > THRESHOLD
&& this.lastRecordedTemperature <= THRESHOLD
) {
// publish event
this.subscriptions["above"].next(currentTemperature);
} else if (
currentTemperature <= THRESHOLD
&& this.lastRecordedTemperature >= THRESHOLD
) {
// publish event
this.subscriptions["below"].next(currentTemperature);
}
this.lastRecordedTemperature = currentTemperature;
}
Whenever
next
is called the on
API would be triggered; by design, the callback would be called.Subscribing for event
When the temperature is
below
30°C then ac should go off, and the window should open; the opposite should happen for above
event 30°C.thermostat.on("below", t => {
this.ac = false;
this.window = true;
});
thermostat.on("above", t => {
this.ac = true;
this.window = false;
});
Wiring all pieces together.
Fiddling
Any variation you make with the above code itself a pattern:
Previously published here.