In a recent project, I’ve gotten into the habit of using the timer operator inside RxJS. At first I thought it was quite hacky, but actually.. It can come in incredible useful in scenarios that you may have previously used setTimeout. That might make it sound even worse! But let me explain.
In my particular case, I needed to load an Esri map on the page. If you’ve never heard of that before, just think of it as a Google Maps style widget. However, loading this widget could max out bandwidth on some connections as it tried to load many tiles (Images of the map) all at once. Because of the async nature of my application, I was also trying to load some important information to display side by side with the map. This information was far more important than loading the map fast, and yet, they were competing with each other for resources.
What I really wanted was just a small delay in loading the map to give a chance for other requests to go through first. This was somewhat hacky but actually worked well. My first iteration was simple with a timeout like so :
let mapLoader = setTimeout(() => this.loadMap(), 130);
//Somewhere in my ngDestroy
clearTimeout(mapLoader);
This worked actually just fine. But my main issue is that I’ve introduced a new paradigm for “unsubscribing” from observables, in this case we use the clearTimeout method to remove timeouts. What I wanted was a way to use RxJS, so that when I unsubscribe from all my other subscriptions, this simple timer is also unsubscribed.
And easy enough, RxJS has just the thing! Timer.
We can change our code to look like so :
import { timer } from 'rxjs';
let mapLoader = timer(130).subscribe(x => this.loadMap());
Simple! All this does is set a timer to go off in 130ms. Best of all, it returns a subscription just like any other Observable.
If we wanted to, we could also do something like so :
import { timer } from 'rxjs';
let mapLoader = timer(130, 130).subscribe(x => this.loadMap());
So run our loadMap() method in 130ms, and then run it again *every* 130ms after that. These numbers can be completely different, for example :
import { timer } from 'rxjs';
let mapLoader = timer(0, 130).subscribe(x => this.loadMap());
Run right now, and *then* run every 130ms etc.
While Timer might not be used in every project, it can come in incredibly handy as either a delay, or a much nicer way to have repeating timers without having to use recursive setTimeouts. And best of all, they fit with the existing paradigm of Observables/Subscriptions within Angular.
💬 Leave a comment