Check out a free preview of the full Rx.js Fundamentals course

The "Racing Data" Lesson is part of the full, Rx.js Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Steve live codes an improved loading indicator that displays based on how long the loading indicator has been displayed and how fast the fetched API data has been retrieved. The race operator will determine and use the Observable that emits first.


Transcript from the "Racing Data" Lesson

>> So we think about this, what we want to do is we need to start racing some things, right. We want to race the different, like whether or not we should show the loading indicator, when the data came back, did we show a loading indicator for long enough.

These are various things that we need to figure out and coordinate between. Our code has a little bit of a problem here as well, which is we are getting these values at initialization. So I haven't adjusted to many of the numbers yet, but these should probably be moved in as well.

So we'll go ahead, we'll grab these and, We'll pop this in here. This is our same passable but not good version that we had before, right. Again, sure, it doesn't flash a loading indicator real fast, but also it delays things we can do better. So we could theoretically we get our data, and what we need to do is we want to race between whether or not we should show the loading.

And whether or not, we want to race between whether I wish to show the loading and whether the data came back, right. And so we could let's get our data into a variable over here so we can play around with a little bit more. So then we'll call this data.

So now we've got the kind of three pieces that we need to deal with here. So first of all, whether or not we should show the loading should probably be a race between the data and the loading, whichever happens first should be good to go. So let's call this one, I don't know, The idea of whether or not you're loading.

That's a good point. It will theoretically work, but we can do better. Mark's in charge naming things, so we'll deal with that in a second. We got show loading and the data, right, whichever one of these emits first should theoretically win. Right, so okay, one of these should happen and then we'll do the next one and then the last one, then we'll have a little bit of a problem here but we'll deal with that.

We fetch, let's see, res should show loading or data. Yeah, we want the API to be faster at this point. So we'll say show loading after two seconds but our API should go back after one second. Let's refresh that. So API comes back as one second, two seconds.

So we got our data back and we still showed it, so we gotta deal with that in a second. All right, let's see what we got here. So we've got our data, we're going and fetching the data a second time which feels weird. So we'll have to handle that as well.

Hide loading. You could actually make this a timer. We're gonna say that hide loading, is only fire after whatever we're looking for. Right, so this one will delay and then do the thing, this one will fire after a certain amount of time. So we've got both of these in place.

Should we show the loading? Really, we should show it, then we want to hide it depending whichever one happens first. So we want a window here of should we show, should we hide? And then what should we do in this case? See what we got here. All right, this still isn't working right, we're fetching.

Our results are our initial values. Let's go ahead and say show the letter. Yeah, cool. Well this has turned into true on me, let's see. 29, show loading, We're fetching a second time.
>> Do you wanna remove the data from your concat since it's in the race?
>> Yes, well this could be slightly problematic because we also, what happens if show loading wins?

>> Never fetch.
>> Yeah, so we would basically just deal with it. Even if this happened, we'd fetch, but we'd never hear about it, right. So let's see. So we've got our ability to fetch the data, let's go up a little bit. We had the ability to show the loading, faster data, than hide it, right.

Now we could race the two of them, right, the show loading and the should show loading, right. And that's kinda what we should do first, we show the data then we hide it, still problematic. Next, what we could do is figure out how to say, hey, to your point, I want this data one way or the other, right.

Because we know from our earlier when we were learning that every subscription will fire off another request, right. But I both wanna race the loading indicator with the data. But then if I grab on to that data later, and you have it, I still want it, right. So I would like to be able to subscribe multiple times so that fetch of data, so I can hopefully race them together a little bit better.

And there are a few different operators that help us with this, right. One of the questions I got earlier were hot versus cold observables a cold one is your normal observable. Every subscription gets a new version, fetch data will do a from interval or from fetch rather and go get it and give it back to us.

In our case, we could either use share or share replay. Share is basically now a hot observable, right, and so everyone that gets it gets the same copy of the observable. Share replay does kind of what the name says on the tin, right. It's shareable, but it will also give you some number of values in the past, right.

This way it is already completed and we had that data and we missed it, give me, cuz this thing really only shows that data. So give me what it had as its data at the time. And so I show up late to the party, I can have that as well.

So let's try that out. Don't know why keep making a typo, so we'll do share replay. One, again, share, you might have missed some of the previous transmissions, but you'll hear for all new things. Share replay is will also give you a stream of the last n number of values that were omitted that you might have missed.

Cool, so we've got the data, fetch data, we're gonna be able to share that between different observables. Whether or not we should show the loading, we will delay, that's a part of my issue, where we want to show after, all right. So we'll have a value that we're gonna delay and then we're gonna show the loading indicator.

So they were set both by it was taking it down and showing it at the same time, right. So we've got this show loading which is gonna delay, and then now at the correct amount of time show our value. High loading is just a timer that's set to do the thing, but then probably we need to actually, we really wanna grab the first event off of there.

So we'll pipe it.
>> We need to show load it false, we'll never hide.
>> Where's that?
>> Don't need to-
>> Well this is when we want to show it. We're saying we're gonna show it, we're gonna wait until a certain number of milliseconds, then we're going to show it.

Hide loading is gonna be the one that takes it down. Cuz two things, right need to figure out whether or not we should hide the loading, right. If it has been long enough and the data comes back, we don't need to go for a victory lap for another 500 milliseconds, right.

We showed it, we didn't flash in front of them. It is only if the data came back so fast that it would flash, then we need to deal with that. So high loaded, we're basically a timer. It's like loading indicating went up, we're timing the loading being there.

We want to make sure the loading was there for a certain amount of time. If that time has passed and we're not gonna flash anything, soon as the data comes back take it down, right. So basically, high loading really just cares about when we started showing the loading, and really we only want the first as we saw before.

Cool, and I keep putting semicolons in there. So show loading, take an event, delay it, show it would need to show. All right, I could pass the value through it too if I wanted to. So I could say, Now we have a timer that's going to go off, right, that we want to start after we show the loading, right.

So immediately fire the event for showing the loading, that's still gonna delay. After that we are going to fire whether enough time has passed to take it down, and then also the data can pass if it's already happened. So basically what to play through the events in order.

Show the loading that's going to still delay itself. It's gonna fire, but then it's gonna wait before it does that tap. So it fires immediately, second thing that happens, it's gonna delay, it's gonna tap, it's gonna show the loading, that's the first one. After that we're showing the loading, set a timer for how long things should happen before it takes down, then we'll have data actually clean it up.

So you'll notice that hide loading isn't actually doing it, it's like we could even call this timeToHideTheLoading Right, so we should show the loading, which will theoretically race these two. So loading actually should show loading changes a little bit because we want to race this whole process with the data itself.

So here we're gonna say, basically what I just said in words. Immediately start the process of delaying yourself a little bit of time before you show the loading. So we'll say that. Then, if you have shown the loading indicator at all, if that has ever happened, right, set a timer to take it down.

However, don't take it down unless you have some data, right. [LAUGH] Don't tell me we're done loading if you're not done loading. So then the third thing, Is to take that data, And that's when we'll pull down the loading indicator. Right, so this is just handling whether or not we should show loading at all, data dollar sign.

That whole process of spinning up tiny when you should take it down, should race with the data. Cuz if the data comes back before we show I don't care about any of this, right. It's only if this first event triggers then I want to show the loading indicator.

I'm wanna keep it up for as long as it's supposed to be kept up. And then when the data finally comes back in, I wanna take it down, right. So this will be roughly the delta between when we decided to show it and however long we said it should be up.

If you can get away without showing it, please do, but if you're gonna show it, set another timer for the bare minimum it should be up. And then when the data comes back, take it down. If the data comes back in that window we're still gonna leave it up there.

We can deal with the data simultaneously as well. So now we can race, this should show loading and the data itself. All right, so we're gonna say that the API takes, We'll show this, but show the loading indicator for at least, I don't know, five seconds. So a little ridiculous, but.

So loading goes up, the data is received, It comes back, it takes it down. Now five seconds is ridiculous, we shouldn't show that. What happens if the API request comes back in 500 milliseconds? All right, let's just console clear. So this case we're back, no loading indicator, right, we didn't show it at all.

This one we're gonna have the API response come back, JavaScript timers are weird, let's give ourselves like 200 milliseconds of wiggle room there, right, cuz it could still be slightly off with a fake timer. We'll show it, but again, we'll keep it. All right, if you're gonna show it, the data is back, but we're still showing it for a little bit.

Now 500 milliseconds is, again, for a dramatic effect. But again, you'd probably time that to be, I feel like 300 is the threshold for not seeming ridiculous. Now even that was, you adjust it, right, 300 even seemed a bit much Yeah, so you can play with the numbers a little bit.

But yeah, this is the tricky part of kind of pulling together a lot of these concepts. Why would you want to concatenate stuff? Because again, we through a event into the future of showing the loading, soon as we show the loading, then we set a timer for the bare minimum to take it down.

And then if we have the data, if not keep waiting for the data and take down the loading. But if the data comes back before any of this it wins, forget this, ignore this, forget all this complicated logic, we don't wanna deal with it, right. And that's where you can start to play with the time, race different pieces of the timeline against each other.

Be able to orchestrate and coordinate different things in different scenarios, so on and so forth, right. And so what RXJS seeks to do for us is it seeks to give us kind of the tools for kind of playing with all of these things that might happen over time to figure out which one happens first, how to coordinate them.

What order do we want to merge them all in? Do we want to switch between another one? Do we want to finish what we started before we do the next thing, right. What are all the different things that we wanna kind of compile and play around with, right.

But a lot of the pieces from the very simple like turning things into observable with for and of, to do bouncing things, to switching between API's. To putting things in a given order or figuring out which one ends up first. These small fundamental pieces can become kind of the bigger like core of how you build the more complicated things.

Cuz the tricky part is you'd have to squint at this code and read through it totally, right, but it's not a lot of code, right. The tricky part is the actual logic of, okay, so when do I want to show this thing and when do I want to take it down, right.

And that's unfortunately a complicated problem, JavaScript aside, right. It's just our job as software engineers is to effectively work through all of these weird contingencies and edge cases, and sometimes it gets a little squirrely. But ideally, when it comes time to sit down and start figuring out the code.

And we could probably break this out into some smaller methods and stuff along those lines annotate it a little bit better, but to begin to figure out those things. And I think that without a decent abstraction for dealing with things that happen over time. You'd be setting a whole bunch of weird variables that you would try to keep in state, right.

Okay, now I'm gonna set this one to true and then I'm gonna set date dot now plus the amount of interval, and then when the thing comes back I'm gonna say if date dot now is greater than the thing. I'm already frustrated, just I can't even, right. And so to give ourselves tools we're kind of managing all these things.

Again, it's all JavaScript under the hood, right, but again, give us abstractions for handling all of those things as well.

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