首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >当我重新访问一个页面时,Subscribe触发两次

当我重新访问一个页面时,Subscribe触发两次
EN

Stack Overflow用户
提问于 2019-04-09 21:12:55
回答 6查看 2.9K关注 0票数 4

我遇到了订阅2倍的场景。但是,如果我通过复制粘贴轮询器方法到我的组件中来摆脱这个服务,那么这个问题就解决了。

我运行的是Ionic 3,但我不认为这很重要。"rxjs":"5.4.3“

ngDestroy()上调用unsubscribe()

my-service.service.ts

代码语言:javascript
复制
public pollingDataReceived = new Subject<any>();

pollForData = (id: string) : Subscription => {
    let stopPollingForStatus = false;
    return Observable.interval(environment['pollingInterval'])
          .takeWhile(() => !stopPollingForStatus)
          .concatMap(() => {
            return this.getAnalysisById(id);
          })
          .subscribe((analysisData) => {
            if (analysisData) {
              if (analysisData.status === 'questions') {
                stopPollingForStatus = false;
              }
              else {
                stopPollingForStatus = true;
                const result = {
                  someData: 'whatever'
                };
                console.log('raise pollingDataReceived event');// This happens ONCE
                this.pollingDataReceived.next(result);
              }
            }
            else {
              alert('no analysis data!');
            }
          });
  }

my.component.ts

(订阅者)

代码语言:javascript
复制
  private pollingData: Subscription;

  someEventHandler() {
    this.pollingData = this.pollForData(this.id);
  }

  ngOnInit(): void {
    this.myService.pollingDataReceived.subscribe((data) => {
        this.analysis = data.analysisData;
        //This is getting called 2x.  Maybe I double subscribed?
        myNavigator.navigateToPageByStatus(myPage);
    }, (err) => { console.log(err); });
    }

  ngOnDestroy() {
    console.log('ngOnDestroy: unsubscribe pollingData in flow');// This does get called
    this.pollingData.unsubscribe();
  }
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2019-04-09 21:37:45

我遇到了一个类似的问题,尝试下面的代码,这只是一个潜在问题的变通方法。

代码语言:javascript
复制
this.pollingDataReceived.next(result);
this.pollingDataReceived = new BehaviorSubject<any>(); // Here, create new object with null value
票数 1
EN

Stack Overflow用户

发布于 2019-04-09 21:35:53

除非在组件级别提供,否则Angular Services的行为就像单例一样。因此,pollingDataReceived主体将继续持有其订阅,直到服务进入作用域。

在你的例子中,之前访问的对this.myService.pollingDataReceived的过时订阅也被解雇了。因此,订阅者在重新访问时在上触发两次。

在类似于pollingDatangDestroy上清理它可以解决这个问题。

票数 3
EN

Stack Overflow用户

发布于 2019-04-09 23:20:37

处理程序触发两次的原因是,当您多次推送到此主题时,您永远不会取消订阅服务pollingDataReceived主题。您的服务可能只创建了一次,而您的组件通过页面重新访问被重新创建了多次。组件被销毁,但它们对同一主题的订阅仍然完好无损。

解决此问题的最简单方法是以@ashish.gd suggested的身份在component ngOnDestroy method中取消订阅此主题。

每次使用()时,都会创建新主题,这可能会导致内存泄漏。因为您的旧订阅将继续收听旧主题。当心。

虽然最简单的方法是取消订阅pollingDataReceived主题,但更好的方法是让您的服务pollForData()返回一个可观察对象。

除非你需要多个用户来阅读same pollingDataReceived主题--你不需要在那里订阅。下面是一个反映这一想法的示例代码:

代码语言:javascript
复制
pollForData = (id: string) : Observable => {
  return Observable.interval(environment['pollingInterval'])
    .concatMap(() => this.getAnalysisById(id))
    .takeWhile(data => data.status === 'questions')
    // other handling logic goes here
    // .map(), .switchMap(), etc
    // NOTE: no subscription here
}

在控制器中,你可以像这样做

代码语言:javascript
复制
// just an utility subject to track component destruction
onDestroy$ = new Subject();

someEventHandler() {
  this.pollForData(this.id).pipe(
    // this will ensure that subscription will be completed on component destruction
    takeUntil(this.onDestroy$)
  ).subscribe((data) => {
      this.analysis = data.analysisData;
      myNavigator.navigateToPageByStatus(myPage);
  }, (err) => { console.log(err); });
}

ngOnDestroy() {
  this.onDestroy$.next(void 0);
}

--

备注1:似乎目前你的服务是在模块级提供的,这意味着如果你有两个消费者同时请求pollForData(id) (例如,一个页面上的两个组件)-这两个请求都会“写入”到中相同的主题。容易出错的行为。

注释2:目前在您的代码中,只有在流上获得一个新的事件之后,才会运行takeWhile谓词

代码语言:javascript
复制
Observable.interval(environment['pollingInterval'])
  .takeWhile(() => !stopPollingForStatus)

这意味着您将在内存中为environment['pollingInterval']时间进行不必要的订阅。这不应该是关键的,但根据时间的不同,它可能会带来麻烦。

--

希望这对你有所帮助,祝你编码愉快!

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55593785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档