I just recently upgraded to Angular 11.2.9 and RXJS 6.6.7 . I have this in my component ...
ngOnInit(): void {
window.addEventListener('blur', this.onBlur, false);
...
}
...
onBlur(): void {
this.trendingSet$ = timer(1, HotComponent.REFRESH_INTERVAL_IN_MS).pipe(
switchMap(() => this.apiService.getTrending()),
retry(),
share(),
takeUntil(this.stopPolling)
);
console.log(this.trendingSet$);
this.trendingSet$.subscribe((result: TrendingSet) => {
this.articleStats = result.trending_articles;
});
}
However, I'm getting this error on the
this.trendingSet$.subscribe((result: TrendingSet) => {
line:
ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
RxJS 4
onBlur hot.component.ts:90
Angular 14
ngOnInit hot.component.ts:35
Angular 21
RxJS 5
Angular 8
emit
checkStable
onHasTask
hasTask
_updateTaskCount
_updateTaskCount
runTask
drainMicroTaskQueue
core.js:6210
Angular 3
RxJS 5
Angular 20
RxJS 10
onBlur hot.component.ts:90
Angular 14
ngOnInit hot.component.ts:35
Angular 21
RxJS 5
Angular 8
What's the proper way to set a timer in my component to regular query a service method?
Dont use window.addEventListener('blur', this.onBlur, false) when you have rxjs wrapped fromEvent...
The initial problem here is that when you call onBlur as a callback to 'blur' event, pointer this (in this.trendingSet$) will point to Window object and not your component, in that case you have to use window.addEventListener('blur', this.onBlur.bind(this), false)
Also, share operator is redundant here unless you are using stream this.trendingSet$ on other places as well
EDIT
private startPolling$ = new Subject();
private stopPolling$ = new Subject();
// Using this logic, subscription to blur event will be automatically unsubscribed once Component is being destroyed
@HostListener('window:blur', ['$event'])
onBlurEvent(): void {
this.startPolling$.next();
}
ngOnInit() {
const poll$ = timer(1, HotComponent.REFRESH_INTERVAL_IN_MS)
.pipe(switchMap(() => this.apiService.getTrending()), retry());
this.startPolling$.pipe(
switchMap(() => poll$),
takeUntil(this.stopPolling$)
).subscribe((response) => {
// Doing stuff with response
});
}
Or instead of using @HostListener you can use
const poll$ = timer(1, HotComponent.REFRESH_INTERVAL_IN_MS)
.pipe(switchMap(() => this.apiService.getTrending()), retry(),
takeUntil(this.stopPolling$));
fromEvent(document, 'blur').pipe(
switchMap(() => poll$),
).subscribe((response) => {
// Doing stuff with response
});