为什么观察者方法被调用两次?

时间:2018-04-11 14:45:41

标签: angular rxjs observable

我有以下返回observer的方法,但它被调用两次:

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 
});

3 个答案:

答案 0 :(得分:3)

这种情况正在发生,因为您订阅了两次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;

  }
});

这样您就可以在您的信息流中添加一个操作员,直到您在回程中订阅它为止。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

// 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);
      })
    );
}