【问题标题】: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 中,如何使用 RXJS 设置计时器(例如,避免“TypeError: You provide 'undefined' where a stream is expected”错误)
【发布时间】:2021-04-21 00:39:29
【问题描述】:

我最近刚刚升级到 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

在我的组件中设置计时器以定期查询服务方法的正确方法是什么?

【问题讨论】:

    标签: angular timer rxjs angular11


    【解决方案1】:

    当你有 rxjs 包装 fromEvent 时,不要使用 window.addEventListener('blur', this.onBlur, false)...

    这里最初的问题是,当你调用 onBlur 作为 'blur' 事件的回调时,指针 this(在 this.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
       });
    

    【讨论】:

    • 你说不要使用 'window.addEventListener('blur', this.onBlur, false)' 但有什么替代方法?
    猜你喜欢
    • 1970-01-01
    • 2018-10-19
    • 1970-01-01
    • 2020-12-13
    • 2014-06-29
    • 2015-10-11
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    相关资源
    最近更新 更多