Throttling Events in Angular with Rxjs
Tags: angular, rxjs
Published: 2019-05-27 11:18:58

---
title: Throttling Events in Angular with Rxjs
published: true
tags: angular, rxjs
canonical_url: 
---

Both Angular and Rxjs give you the ability to easily listen to events. Using Angualr's @HostListener() annotation allows a declarative binding while using Rxjs event binding allows for filtering, debouncing and throttling of events, to name a few.

The prefered way to bind to events in an Angular component is to use the `@HostListener()` annotation. This provides a clean declarative binding from an event to a method, and best of all works without the need to access any browser specific APIs such as `document` or `window`. Avoiding direct browser DOM APIs becomes important if you want to use the Universal server-side rendering or run the applicaton in a WebWorker. Keeping your code open to either of these possibilities, even if you have no plan at the moment, allows you to take advantage of future optimizations.

### Throttling Resize

You may ask, _why do I need to listen to resize events?_

You may not need to. As many of your UI elements as possible should respond to form factor changes through CSS cues rather than scripted cues. Mobile and Tablet devices don't have any real stories where the viewport changes sizes that aren't handled by the `deviceorientation` event. Their are probably some edge cases like split screen and some virtual keyboards pushing up on the browser window.

Their may be some exceptions to this where you will need to script the responsiveness. For example, you may have a menu that is pinned open on desktop form factor, pinned in a minimized mode on tablets in landscape mode, and hidden behind a hamburger menu on portrait tablets and phones.

Even with this scenario a valid situation where a user is resizing, not rotating, the browser window is at best an edge case.

In reality the use case is a developer story. As a developer you want to be sure that your UI behaves at every width between the smallest acceptable width to the largest. You want to be able to stretch your responsive browser developer tools from tiny to extra-large and ensure that the app will display correctly for every pixel width.

With Rxjs we can accomplish very simply:

<figcaption><span>
</span></figcaption>

```typescript
private resizeObservable = Observable.fromEvent(
    window, 
    'resize'
  ).throttleTime(200);
```

Nice and clean. But there is a problem with this. We are accessing the DOM `window` directly. We could wrap this in a try/catch, or inject a _window_ into our component that gets replaced with a fake if we run on the server, but then if we decide to run in a WebWorker we are out of luck and will need to replace this code.

### The Solution

We can use the Rjxs throttle method in conjunction with Angular's `@HostLister()` decorator annotations.

In our example below we create a _Subject_ of type _number_ named `resizeSubject`. We will call the `next()` method on `resizeSubject` in our event handler.

We create an _Observable_ from our _Subject_ and throttle it for 200 miliseconds. Then within our `ngOnInit()` we will _subscribe_ to our throttled observable.

<figcaption><span>app.component.ts
</span></figcaption>

```typescript
export class AppComponent implements OnInit { 

  private resizeSubject = new Subject<number>(); 
  private resizeObservable = this.resizeSubject.asObservable()
    .throttleTime(200); 
 
  @HostListener('window:resize', ['$event.target.innerWidth']) 
  onResize(width: number) { 
    this.resizeSubject.next(width); 
  } 

  ngOnInit() { 
    this.resizeObservable.subscribe(x => 
      this.doSomethingWithThrottledEvent(x)); 
  } 

  private doSomethingWithThrottledEvent(width: number) { 
    // . . . 
  } 
}
```