Check out a free preview of the full Asynchronous Programming in JavaScript (with Rx.js Observables) course

The "Composing a Stream" Lesson is part of the full, Asynchronous Programming in JavaScript (with Rx.js Observables) course featured in this preview video. Here's what you'd learn in this lesson:

As the forEach function is called on the JSONP Observable, Jafar breaks down what the incoming data is going to look like to better explain which functions will be necessary to compose the stream.


Transcript from the "Composing a Stream" Lesson

>> [MUSIC]

>> Jafar Husain: Let's listen, first. Let's go through the process, the problem-solving process. The first is we take, comment that out so it doesn't keep. We take the streams that we have, like key presses. And, in this case, the search results that come out of getWikipediaSearchResults. And we compose them together to create the stream that we want.

What's the stream that we want? We have to start there. We have to decide, what is the stream of data that we actually want? This is an autocomplete box. What I want is the stream of all of the search results that come back from the server. Sometimes, when you're trying to figure out the stream that you want, it helps to work backwards.

Which is to say, what would I do with the data that comes out of the stream? What are we gonna do with the data that comes out the search results that come back from the server?
>> Jafar Husain: Anybody tell me, in an autocomplete box? What's the action where we do something, where we change something?

>> Speaker 2: [INAUDIBLE] live search [INAUDIBLE]
>> Jafar Husain: Yeah, when a search result comes back from the server, we wanna put it on screen. That's the thing where we're changing something, changing something inside of the browser. I'm gonna create a spot inside of here. We're not gonna be too fancy with the formatting here.

We're just gonna create a spot to store our search results. For now, I might even just make it a text area, and we'll make it a something a little fancy later.
>> Jafar Husain: I might just fork right now.
>> Jafar Husain: That looks scary. Save that.
>> Jafar Husain: So now we've created a little spot on screen to store our search results.

If I had to script JS,
>> Jafar Husain: What I wanna do is I wanna start with key presses. Obviously, everything starts with a key press, right? I'm gonna create my searchResultSets observable. The searchResultSets observable is going to look like this. If you were to to visualize it, it would be an observable.

Remember, my special syntax for observable. This is the syntax I'm inventing, which is this collection of items over time. If we were to picture what searchResultSets is gonna look like, it's gonna look like this. Let's say we type a, and then we type b. We're gonna get an observable array of results.

And the fact that it's an array doesn't matter. It could be a number, but it's still a flat observable of results. It just happens to contain arrays. If I type a first, and then I type ab, I'll only be left with abacus. Notice, this searchResultSets observable is gonna go on forever.

It's never gonna stop because, at any moment, somebody could hit a key press. That's the observable that we want to create. What observables do we have? We have key presses, and what does it look like? Well, what would a key press look like? Something like, it's actually an event object, but something like this.

If we were to just pull out the key that was pressed, that's what key presses would look like. How do we go from this, and this? It's a long function name.
>> Jafar Husain: What will getWikipediaSearchResults look like, if we were to visualize it as an observable? It would be an observable that goes on for a long time.

And then, eventually, gives us these results. And then completes. Notice that it completes.
>> Jafar Husain: As you're building observables, it's really helpful. And I recommend this as your coding, to comment on top of these observerables. Actually comment and use the stream to convey what the streams gonna look like.

You can actually visualize it using this fake syntax here. So we've got key presses. We start off with this infinite observable of a, b, c, whatever they happen to click. And now we've also got getWikipediaSearchResults. Which, when given a term, will give us an observable that will eventually give us an array of search results that end.

How do we put them together to build searchResultSets, which is an infinite observable of search results? Because this is the problem. It's how do you take the event that you want? And then take the events that you have? And squeeze them together to create the one that you want?

I want some brain-storming ideas here. How can I ease this? It's always just a little bit of time. I'm gonna ease this closer to this, right here. What would be the first operation I might use?
>> Speaker 2: [INAUDIBLE]
>> Jafar Husain: I'm sorry?
>> Speaker 2: The throttle.
>> Jafar Husain: Well, the throttle, yeah.

We talked about, yesterday, that we wanna turn something like this. And that would be turning something like this,
>> Jafar Husain: Into this. keyPresses.throttle will look like this.
>> Jafar Husain: Can anybody tell me why it'll look like that?
>> Speaker 3: [INAUDIBLE]
>> Jafar Husain: Yes. The way throttle works is we get a key.

Then after certain duration, if we get another key, we drop the previous key and we keep that key. Then we wait a certain duration, and if nothing happens. If another key doesn't come in, then we return the item. So now that we're visualizing it, we can start to see how these operators transform the stream.

Let's say, fine, we do a throttle. Now, how do we go from this to this?
>> Speaker 3: Does throttle use switchNext, or whatever that one is?
>> Jafar Husain: Doesn't use switchLatest. switchLatest would only work on a two-dimensional observable. In this case, under the hood, it just you know creates a timer using something like setTimeout to keep track of it.

How do we get closer, here, guys? We've got a stream of keys and we wanna, somehow, turn it into a stream of search results. It's almost like we wanna substitute each key for search results. Map, I hear map. I'm gonna start out coding here, keypresses, and I'm gonna code a map.

So we've got a key in here. Let's throw in a throttle as well. Because we know we want to do that to make the screen a little less chatty.
>> Jafar Husain: Let's just give it 20 milliseconds. As we go, I'm gonna paste above, and I think this is a nice thing to do.

Paste above what it looks like at every stage. As you're going through your code, this is a nice way to comment your code. If you want folks to understand what's going on. This is actually a nice technique to use as you write code. To keep showing what an example stream would look like after the transformation.

For every key, what do we wanna substitute in this place? What do we wanna replace the b key with? I think, ideally, the search results for B.
>> Speaker 3: Yeah, an array.
>> Jafar Husain: An array? Yeah, you're right. Absolutely an array. Right, good. The array of search results for that.

How are we gonna get there, though?
>> Jafar Husain: We know that getWikipediaSearchResults will give us an observable of array. That's a little bit closer than the key press.
>> Speaker 4: We have to call the for each of the Wikipedia search results, right?
>> Jafar Husain: Good thinking, good thinking, but here's the thing.

We're only going to call for each once in this program. Because, remember, we're gonna separate our code into two parts. One, we're going to build the stream that we want. And you don't use for each at all to do that. Once we've built the stream that we want, then we're gonna call for each.

And we're gonna do something with it. So now the only choices on the table are map, filter, concatAll, switchLatest, mergeAll, and reduce.
>> Speaker 3: I was gonna say maybe concatMap, because we don't necessarily need to be that layer deeper.
>> Jafar Husain: Interesting. So you're saying, if we map. Why don't we start with map and come back to the concatAll.

Because, remember, the technique, guys. Keep mapping until you've got everything in scope that you need to build your search result. And then at the end, figure out how deep you are and flatten it out again. How do we how do we get closer? We know we've got this function.

Wouldn't it be better if we substituted this for an observable of the search results for b? That would be closer. Let's just, using map, cuz map's all about substitution. We can replace b with the getWikipediaSearch, do I have that name right? Yep, getWikpediaSearchResults. Now, am I going to use the key?

Do I wanna search for b?
>> Speaker 4: No, you're gonna use the value of the textbox.
>> Jafar Husain: Absolutely, I'm gonna pull up the value of the textbox. So now what does our stream look like?
>> Jafar Husain: Let's say I typed a first, and then I type b.
>> Jafar Husain: What if, while the request is going out for a, somebody types b, and now is searching for ab?

We actually start another network request while we're waiting for the previous one. Concurrency, and it's going, it's going. And now we're only left abacus. How many dimensions deep are we? How many dimensions of observable do we have?
>> Speaker 2: Two.
>> Jafar Husain: A two-dimensional observable.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now