angular2: How to use observables to debounce window:resize
I think that you can't debounce this way using observable. In fact, such things aren't supported out of the box right now but there is an open issue for this:
- https://github.com/angular/angular/issues/4062
To achieve your goal, you could use directly the Observable.fromEvent
to get an observable for this event. So you can apply the debounceTime
operator on this observable.
Here is a sample:
@Component({
(...)
})
export class App {
size: number;
constructor() {
Observable.fromEvent(window, 'resize')
.debounceTime(1500)
.subscribe((event) => {
this.doSmth(event);
});
}
doSmth(e: Event) {
console.log('do smth');
this.size = e.target.innerWidth;
}
}
See this plunkr: https://plnkr.co/edit/uVrRXtnZj8warQ3qUTdN?p=preview
In one of our apps we also had the implementation Thierry Templier proposes, but I noticed that Angular's change detection is firing (a lot) on window resize, which makes our app slow on resize.
Fixed it by using zones & Subject, like so:
private changeSubject = new Subject<number>();
constructor(private zone: NgZone) {
this.zone.runOutsideAngular(() => {
Observable.fromEvent(window, 'resize')
.debounceTime(1500).distinctUntilChanged().subscribe((e: Event) => {
this.zone.run(() => {
this.changeSubject.next(e);
})
}
)
});
this.changeSubject.subscribe((e: Event) => { this.doSmth(e); });
}
See plunker with the issue here (resize screen and watch console).
And plunker with the fix for this issue here (resize screen and watch console).
You can use @HostListener decorator. This is a common way to subscribe events like this.
@Component({
// ...
})
export class App {
private changeSize = new Subject();
constructor() {
this.changeSize
.asObservable()
.pipe(
throttleTime(1000)
)
.subscribe(innerWidth => console.log('innerWidth:', innerWidth));
}
@HostListener('window:resize', ['$event.target'])
public onResize(target) {
this.changeSize.next(target.innerWidth);
}
}
You can read more about @HostListener
here or here.