Introduction
This is a note on RxJS subjects.
Background
Element based programming has been increasingly popular in web applications. Regardless if you use React or Angular, or if you choose not to use any of the frameworks, an RxJS subject can be useful to communicate among different programming units.
An RxJS subject is a JavaScript object that broadcasts notifications to all the subscribers from any publishers.
Besides giving some simple examples, this note talks about how to keep an RxJS subject alive after an error is broadcasted through the subject.
The attached is a Maven project with three small examples. But you do not need to have Java to run it. All the examples are in the HTML files. You can host the HTML files in any web server.
A Basic Example on RxJS
Let us take a look at the "rxjs-1-basic-example.html" first. An RxJS subject is pretty easy to use. In order to save my effort to describe how an RxJS subject is used, I will recommend you to take a brief look at the RxJS document before looking at the example.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>rxjs-1-basic-example.html</title>
<link rel="stylesheet" type="text/css" href="styles/app.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>
<script type="text/javascript">
let ClockSubject = new Rx.BehaviorSubject('');
let SubscribeToClockSubject = function(eId) {
let element = document.getElementById(eId);
ClockSubject.subscribe(
function(time) {
element.innerHTML = time;
},
function(error) {
element.innerHTML = error;
}
);
};
window.onload = function() {
SubscribeToClockSubject('clock1');
SubscribeToClockSubject('clock2');
SubscribeToClockSubject('clock3');
let getTime = function() {
let d = new Date();
return d.toLocaleDateString() + ' ' + d.toLocaleTimeString();
};
setInterval(function() {
ClockSubject.next(getTime());
}, 1000);
ClockSubject.next(getTime());
};
</script>
</head>
<body>
<div><a href="index.html">Back ...</a></div>
<div id="clock1" class="clock"></div>
<div id="clock2" class="clock"></div>
<div id="clock3" class="clock"></div>
</body>
</html>
In this example, I added three "div
s" in the HTML. The goal is to display the current time in all the "div
s". A "setInterval
" callback is used to get the current time for every second. It is sent to all the subscribers through an RxJS subject named "ClockSubject
".
- A publisher can publish a notification to all the subscribers through the "
next()
" method on the subject; - A publisher can publish an error to all the subscribers through the "
error()
" method on the subject (We will see an example for "error()
" in the second example).
When we subscribe to the RxJS object, we can pass two callback functions to the "subscribe()
" method.
- The first function is the notification callback function. When a notification is published, this function is called;
- The second function is the error callback function. When an error is published, this function is called.
If we load the "rxjs-1-basic-example.html" into the browser, we can see that the time is displayed and continuously updated for every second in all the "div
s". All the subscribers received the notification data for the current time published by the "ClockSubject.next(getTime())
" through the "ClockSubject
".
Opps - Error Is A Problem?
In order to keep the first example simple, we did not try the error notifications. But errors do occur and it is necessary to publish error notifications to the subscribers. Now let us take a look at the "rxjs-2-error-example.html".
let i = 0;
setInterval(function() {
if (++i == 5) {
i = 0;
ClockSubject.error('An artificial error!');
return;
}
ClockSubject.next(getTime());
}, 1000);
In order to test error notifications, I artificially broadcast an error notification for every five seconds.
ClockSubject.subscribe(
function(time) {
element.innerHTML = time;
},
function(error) {
element.innerHTML = error;
}
);
If a notification is received by the subscriber, the "div
" will display the time. If an error is received, the "div
" will display the error message.
If we load the "rxjs-2-error-example.html" into the browser, we can see that the time is displayed and updated. But when an error is received, the whole web page stops. Any further updates on the time no longer take effect.
Error Is A Problem
According to this link, error is a problem. Any "error()
" call to a subject basically kills the subject. It is no longer alive, and it stops broadcasting any further notifications or errors. In this example, any "ClockSubject.next(getTime())
" is not sent to the subscribers after the first call of the "ClockSubject.error('An artificial error!')
".
A Wrapper of the RxJS Subject
In many cases, we do want a subject that keeps alive after broadcasting an error. To keep the subject alive, I created a simple wrapper subject in the "rxjs-3-error-handle-example.html".
Rx.FullSubject = function() {
let self = this;
let nSubject = new Rx.Subject();
let eSubject = new Rx.Subject();
self.subscribe = function(ns, es) {
nSubject.subscribe(ns);
eSubject.subscribe(es);
};
self.next = function(value) {
nSubject.next(value);
}
self.error = function(error) {
eSubject.next(error);
}
}
The "FullSubject
" has two RxJS subjects:
- The "
nSubject
" is responsible for broadcasting notifications - The "
eSubject
" is responsible for broadcasting errors
Instead of using "error()
" method to broadcast the errors, the "eSubject
" uses the "next()
" method. After sending an error, the "eSubject
" is still alive, so the "FullSubject
" is still alive.
let ClockSubject = new Rx.FullSubject();
If we load the "rxjs-3-error-handle-example.html" into the browser, we can see that when an error is sent, the error message is displayed in the "div
s".
But when the time notification is sent, the current time is displayed in the "div
s". The "FullSubject
" remains alive after sending the error messages.
Points of Interest
- This is a note on RxJS subjects;
- An RxJS subject is a JavaScript object that broadcasts notifications to all the subscribers from any publishers;
- The RxJS subjects may be useful to communicate among React or Angular components;
- I hope you like my postings and I hope this note can help you one way or the other.
History