In Angular 11, how do you set a timer with RXJS (e.g. avoid "TypeError: You provided 'undefined' where a stream was expected" errors)
In Angular 11, how do you set a timer with RXJS (e.g. avoid "TypeError: You provided 'undefined' where a stream was expected" errors)
我最近刚升级到 Angular 11.2.9 和 RXJS 6.6.7。我的组件中有这个 ...
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;
});
}
但是,我在
上收到此错误
this.trendingSet$.subscribe((result: TrendingSet) => {
行:
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
在我的组件中设置计时器以定期查询服务方法的正确方法是什么?
不要使用 window.addEventListener('blur', this.onBlur, false) 当你有 rxjs 包裹 fromEvent...
这里最初的问题是,当您调用 onBlur 作为 'blur' 事件的回调时,指针 this(在 this[=30= .trendingSet$) 将指向 Window 对象而不是你的组件,在这种情况下你必须使用 window.addEventListener('blur', this.onBlur.bind (this), false)
此外,share 运算符在这里是多余的,除非您也在其他地方使用流 this.trendingSet$
编辑
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
});
}
或者不使用 @HostListener 你可以使用
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
});
我最近刚升级到 Angular 11.2.9 和 RXJS 6.6.7。我的组件中有这个 ...
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;
});
}
但是,我在
上收到此错误this.trendingSet$.subscribe((result: TrendingSet) => {
行:
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
在我的组件中设置计时器以定期查询服务方法的正确方法是什么?
不要使用 window.addEventListener('blur', this.onBlur, false) 当你有 rxjs 包裹 fromEvent...
这里最初的问题是,当您调用 onBlur 作为 'blur' 事件的回调时,指针 this(在 this[=30= .trendingSet$) 将指向 Window 对象而不是你的组件,在这种情况下你必须使用 window.addEventListener('blur', this.onBlur.bind (this), false)
此外,share 运算符在这里是多余的,除非您也在其他地方使用流 this.trendingSet$
编辑
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
});
}
或者不使用 @HostListener 你可以使用
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
});