- In this section, we're going to start looking
at the Reactive Extensions library
for JavaScript, RxJs.
Very useful if you are dealing
with an Observable stream of data
that's being pumped into your web application,
maybe from a web socket on the server.
At the heart of the Reactive Extensions library,
there's a class called "Observable."
And the basic idea is, it pumps values continuously
into your code from elsewhere.
And you can define a subscriber,
which listens for that data and gets notified
whenever a new piece of data arrives, okay?
So what we'll have a look at then, in this section,
a simple example of how to create an Observable stream
that will be pumping data into my code,
how to subscribe to that stream,
to receive the values as they're emitted,
and how to test that stream, to make sure
that it emits the values that we expect it to emit.
If you wanna follow along,
the demos for this example are in that folder, TestingRxJs.
Okay, so first things first,
Reactive Extensions isn't a standard library in JavaScript.
You have to download it in your package.json.
So in the demo folder,
I've got a dependency for the Reactive Extensions library.
I've also got a dependency for babel/node.
Babel/node is a tool that we'll use
for running our JavaScript, okay,
so that the code can execute,
set up an Observable stream, and then subscribe to it.
We'll run the test and the Jest obviously.
So that's my package.json file.
If you wanna follow along for yourself,
go into the TestingRxJs folder,
open that up in the code editor.
In the code editor, you'll see...
There we go.
Those are my dependencies that I just specified.
Okay? So that's the first step.
Now the Observable class, like I said,
Reactive Extensions is all about the Observable class.
An Observable object represents a stream of data
which is constantly going to be emitting values
into your application, which you can subscribe and handle.
So the first thing we're gonna do,
we're gonna have to create an Observable object,
which outputs or emits data.
So there are lots of factory functions
to help you to create an Observable.
You can create an Observable
that emits data in different ways.
The simplest example, there's an of() function.
Okay? So I've imported in this example, here, my code.js.
I've imported the Reactive Extensions library
for JavaScript.
And then in that library, there's an of() function,
and this function creates an Observable object.
It's a factory function.
It creates a new Observable object,
which creates a new Observable object
that emits a single value.
Here, 42.
Obviously that's my very simple function,
which emits a single value.
Okay. So if you wanna follow along, code.js, okay?
There's my function, which creates an Observable,
which emits a single value.
So when you call that function,
you will get back an Observable object
which will emit a single value.
Okay?
So what we're gonna do now is
to see how to subscribe to that Observable,
that function returns an Observable,
which will emit values or one value.
How can I subscribe to that Observable
to receive the value that it emits?
This is what you do.
You take an Observable object,
like the one returned from that function.
Remember this function is returning an Observable object.
You can take that Observable object,
and you can say ".subscribe()."
And then you give it an object
with three properties, three callback functions.
A callback function properly called "next."
This is a callback function, which will be invoked
whenever another value is emitted.
It's like, "Here's the next value for you."
So the Observable will call you back.
It'll call this function back
whenever a new piece of data has been emitted,
or if the Observable stream raises an error,
then it'll call this callback.
Okay. So you could say, "Process the error here."
An Observable object may close.
It might say, "That's the end of that.
"No more data for you. I've finished."
The Observable object can shut down,
at which point, it'll call this function "complete."
And this is your signal
that there will be no more data from now on.
So you can subscribe to an Observable,
and you can be notified
that the next piece of data has arrived,
or an error has occurred,
or that we are done here and move on.
Okay. So let's put that into practice.
A simple but complete example.
Here's my code, remember,
which creates an Observable object and returns it.
This Observable will emit one value.
Obviously, it's value 42.
So I can call that function.
When I call that function here,
this is my main code if you like.
When I call that function,
it returns back an Observable object.
I can subscribe to that Observable object
and specify a callback inside this callback object.
I'm only interested in handling the next value.
Now, I could also have an error handler
and I could have a complete handler,
but all I'm interested in is saying,
"Tell me when the next value was emitted."
So what happens when this function emits the value 42?
That value will be passed into my callback
to say, "Here's the next value.
"The data is 42, which I then output on the console."
There we go.
So that's the general way of creating an Observable
and then subscribing to it, to receive the next value.
Every time another value is emitted,
this callback function will handle it.
So that's my main code.
In my demo, here's my main code.
Okay. As I've advertised, call the function,
it returns an Observable,
and subscribe to data from that Observable.
Oh, here's the next value.
This is my callback function.
A lambda that'll be invoked when that new data has arrived.
That would be the value 42.
Right? So I could run that sample code.
"npx babel-node main.js"
Okay. So babel/node will allow me to execute,
to run my main code that we just saw,
and it displays the value 42.
So that is the result of this.
Get the Observable object, subscribe to it.
Tell me when the next value arrives.
Oh, here's the next value?
It's the value 42.
Display the value 42 on the console.
Well, there it is.
Okay, so our Observable object was emitting the value.
My client code subscribed to the Observable,
got the result, displayed it on the console.
Great. What about testing it?
Similar kind of idea, really.
This is my test code, in test.js.
Test.js is here.
So call the function as before.
It returns an Observable, subscribe to the Observable,
get notified when the next piece of data arrives.
Okay. In my test, verify that the data
that's just arrived is the correct value, and then done.
We're getting quite used to this idea, now.
When you have callback functions,
Jest doesn't know how long to wait
for the callback to be invoked.
You need to tell it,
"You can move on now. This test is finished."
So I say done, and that tells Jest,
"Okay, that's the end of that function."
We can go onto the next test function.
So remember,
whenever you have some kind of callback mechanism,
the test functions that you write,
you have an extra parameter, a done parameter,
a callback into Jest to tell Jest when you have finished,
and it can move on to run the next test.
Okay. So if I run the tests, this is what it looks like.
I ran the test.
It executed my test function to test
that the Observable emitted the value 42, and it did.
Okay, so that was a very simple example of Observable.
We used the of() function to create an Observable object.
We then subscribed to that Observable,
and in our subscription, we had a "next" callback.
"Call me back with the next value."
We asserted that value was correct in our test.
And then we move on.
What we'll have a look at in the next section is
how to look at some additional techniques to go further
with Reactive Extensions, for JavaScript.