【问题标题】:Why observer method is called twice?为什么观察者方法被调用两次?
【发布时间】:2018-04-11 14:45:41
【问题描述】:

我有以下返回观察者的方法,但它被调用了两次:

public getClassesAndSubjects(school: number, whenDate: string): Observable<ClassesAndSubjects[]> {

    console.log('1');

    const observable = this.classService.GetClassesAndSubjects(school, whenDate);

    console.log("2");

    observable.subscribe(data => {
      if (!data.hasOwnProperty('errors')) {
        this.classesSubjects = data;

      }
    }, error => {
      console.log("ERROR loading GetClassesAndSubjects: " + error);
    });

    console.log("3");

    return observable;
  }

我的意思是一行const observable = this.classService.GetClassesAndSubjects(school, whenDate); 被调用两次并向服务器发送两次请求。

这样称呼:

this.classInstance.getClassesAndSubjects(school, date).subscribe(value => {
   // TODO 
});

【问题讨论】:

  • 你在哪里给this.classInstance.getClassesAndSubjects打电话?
  • 您在浏览器的开发者工具中的“网络”选项卡中看到此问题?
  • 您在方法内部订阅了一次,并且大概在外部订阅了一次......为什么您希望它只被调用一次?
  • İ 通过点击在组件中调用this.classInstance.getClassesAndSubjects
  • 您非常清楚地订阅了两次,一次在 getClassesAndSubjects 内部,然后您订阅了相同的 observable 的返回值。

标签: angular rxjs observable


【解决方案1】:

发生这种情况是因为您订阅了 observable 两次,并且 observable 每次被订阅时都会执行。

改变这个:

observable.subscribe(data => {
  if (!data.hasOwnProperty('errors')) {
    this.classesSubjects = data;

  }
}, error => {
  console.log("ERROR loading GetClassesAndSubjects: " + error);
});

到这里:

observable.do(data => {
  if (!data.hasOwnProperty('errors')) {
    this.classesSubjects = data;

  }
});

这样,您只是将一个运算符添加到您的流中,直到您在返回时订阅它才会执行。

【讨论】:

  • 会试试,不知道这个
  • 实际订阅时处理。
  • 是的,它对我有用!感谢您提供简短而实际的解决方案
  • 你能帮我解决下一个问题吗:我试图从 subsribe 返回准备好的数组:public getChips(classSubjects: any) { Observable.of(classSubjects).map(n =&gt; { return { classNumber: n.classNumber, classSuffix: n.classSuffix }; }).subscribe(x =&gt; console.log(x)); return []; }
  • 订阅不返回值。如果你想在别处获取值,你应该返回 observable 流并在你想要值的地方订阅它。
【解决方案2】:

与 Promises 不同,Observable 的函数在 订阅 时调用,而不是在创建时调用。对 Observable 的每个subscription 都会导致 Observable 的函数再次运行。

如果您想与多个订阅者共享一个 Observable 的发射,请使用share()。否则,如果您只想在排放上标记功能而不订阅 Observable,您可以使用 do()(或 RxJS 5+ 的 tap)。

【讨论】:

    【解决方案3】:

    您遇到了麻烦,因为您在两个地方订阅了相同的方法。

    // Your code that is subscribing to the events in two different places, which is why it is called twice.
    /*public getClassesAndSubjects(school: number, whenDate: string): Observable<ClassesAndSubjects[]> {
    
      console.log('1');
    
      const observable = this.classService.GetClassesAndSubjects(school, whenDate);
    
      console.log("2");
    
      observable.subscribe(data => {
        if (!data.hasOwnProperty('errors')) {
          this.classesSubjects = data;
    
        }
      }, error => {
        console.log("ERROR loading GetClassesAndSubjects: " + error);
      });
    
      console.log("3");
    
      return observable;
    }*/
    
    import { tap, catchError } from 'rxjs/operators';
    import { Observable } from 'rxjs/Observable';
    
    public getClassesAndSubjects(school: number, whenDate: string): Observable<ClassesAndSubjects[]> {
      return this.classService.GetClassesAndSubjects(school, whenDate)
        .pipe(
          tap(data => this.classesSubjects = !data.hasOwnProperty('errors') ? data : this.classesSubjects),
          catchError(err => {
            console.log("ERROR loading GetClassesAndSubjects: " + error);
            return Observable.throw(err);
          })
        );
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-18
      • 1970-01-01
      • 2011-08-26
      相关资源
      最近更新 更多