Implement pause and resume feature correctly through RxJS

André Staltz
InstructorAndré Staltz
Share this video with your friends

Social Share Links

Send Tweet
Published 7 years ago
Updated 5 years ago

Eventually you will feel the need for pausing the observation of an Observable and resuming it later. In this lesson we will learn about use cases where pausing is possible, and what to do when pausing is impossible.

[00:00] Sometimes you will need to create a pause and resume interaction in your app. For instance, imagine that you're implementing polling where every two seconds, you want to make a request to this endpoint.

[00:10] Maybe the data behind this endpoint is going to be different someday, that's why we have polling.

[00:16] Right now, we're doing a request every two seconds. This is going to last forever. That's where pausing would be nice. While a pause and resume is possible in our Ext JS, there are some downsides to be aware of.

[00:29] Ideally, we want to change the behavior of this observable, but that's not possible because this observable was defined to be like this, every two seconds, it emits an increasing number.

[00:43] After it was defined, there is nothing that we can do to change that behavior. We could maybe apply operators but that's going to create new observables based on this observable. We can't actually change how this one behaves.

[00:58] That said, we can apply a trick and that trick involves inserting a new observable which we'll call resume stream and this will emit false or true, so Booleans. We're going to make that as a subject. The subject here is not the important part. You could have done this with observables as well. It's only important that this will emit Booleans. False will mean to pause and true will mean to resume.

[01:25] We're going to start by making it send false so that it's paused. We're going to set a timeout so that after a while, we are going to send true so that it starts, let's say, after 500 milliseconds. We're going to do that. Again, we're going to send false after, let's say, five seconds.

[01:50] How do we use resume here? In this part of the code, we're going to write resume here, and then we're going to map, except we're going to use a switch map. We're going to take that Boolean, and we're going to check, is that Boolean true?

[02:05] If it is, we're going to return this in our observable. If it is false, we're going to return our rx-observable.empty. I'm also going to put here at the end, do just for a console log for debugging purposes.

[02:28] What does the switch map do here is that when we see a true from resume stream, then this stream will behave like this stream. When we see a false, then this stream will behave like the empty stream.

[02:44] The empty stream won't emit any value, so that's why this part won't happen during the execution of this empty. While this one is executing, then we will get those events and that's how the Ajax is going to happen.

[02:59] Let's try running this. Once we start, it starts pause. After 500 seconds, it does a request, and then it does another request. It stopped because five seconds kicked in and we have paused the resume. As you see here, we have requested zero. This zero came from the observable interval. After a while, we had requested one.

[03:26] Now, I'm going to show something interesting where I'm going to resume again, let's say, at six seconds. We're going to see what happens. I'm going to pause at, let's say, nine seconds. We start paused and then after a while, it starts in two requests, and then we pause and then we start again. We pause at nine seconds.

[03:55] Notice, we had requested zero, requested one, and then requested zero. This means that this stream here, the interval, although it behaves like this, it does zero, one and two, etc. We didn't resume and start getting two and three. When we resumed at this point here, we got zero.

[04:23] That means that, as I told you before, we cannot pause and resume this stream, so that's why we didn't get the number two but we just restarted this stream. That's what happened. Once we subscribe again to this inner observable, we're going to start getting the number zero.

[04:39] As you can see, we don't really truly have pause and resume for this observable, but we're just implementing the feature of pause and resume in a way that makes sense for us.

[04:51] This is due to limitations with our Ext JS related to how observables fundamentally work, because after you call subscribe on an observable, you're not anymore in control of how data arrives. Observables are a one way communication of data from that observable to the observer.

[05:10] We can't pause because that would mean that the observer wouldn't be able to send events back to the observable, and that would be a two way communication. That's not really the use case for observables. They are one way communication.

[05:23] There are other features like EA6 generators that allow you to have two-way communication. Observables have different use cases.

[05:31] The important thing is that we were able to implement this pause feature through different ways. It's not a problem that we cannot pause explicitly the specific observable. The lesson is, don't spend time trying to force observables to truly pause and resume.

NWT
NWT
~ 7 years ago

That's actually not fully true. You can create your observable, make custom setInterval inside which will call .next(). And submit pause / resume which will make clearInterval / run interval again.

Mykolas Mikelevicius
Mykolas Mikelevicius
~ 6 years ago

We can't really pause without custom implementation of observable, but if we really need to get interval values from that "pause" moment, we could save the last value and increment respectively. Another approach, which could work in some cases is just ignoring interval values when it is "paused" using windowToggle like here: https://egghead.io/lessons/rxjs-split-an-rxjs-observable-conditionally-with-windowtoggle.

Markdown supported.
Become a member to join the discussionEnroll Today