behaviorSubject return 只有当有新东西的时候

behaviorSubject return only when there is something new

我有以下问题,当我调用 getStudentsList 函数时,它会去服务器寻找我需要的新值,但是 behaviorSubject return 又是当前值(这给我带来了问题因为它用以前的值加载视图),同时我等待服务器信息 return。 我该如何避免这种行为?

  getStudentsList(params): Observable<StudentsListGrid> {
    if (this.studentListSubject$ === undefined) {
      this.studentListSubject$ = new BehaviorSubject<StudentListGrid>(null);
    }
    this.refetchStudentList(params);
    return this.studentListSubject$.asObservable().pipe(filter((value) => value !== null));
  }

  refetchStudentList(gridParams) {
    const subscription = this.http.post<StudentListGrid>(this.baseUrl + 'GetStudents', {gridParams} ,httpOptions).pipe(map(data => this.setDefaultValuesToStudent(data))).subscribe(
      (response) => {

        this.studentListSubject$.next(response);
        subscription.unsubscribe();
      });
  }

通常,您不想为了更新另一个可观察对象或主题而订阅某些内容。相反,将事件与结果联系起来。

private studentListTrigger$ = new Subject();

readonly studentList$ = concat(
  of(null), // triggers a refresh the first time something subscribes to studentList$
  this.studentListTrigger$
).pipe(
  switchMap( // if a new request, drop any previous request in progress.
    () => this.http.post<StudentListGrid>(
      this.baseUrl + 'GetStudents',
      {gridParams},
      httpOptions
    ).pipe(
      catchError(() => EMPTY) // don't let the error of any given attempt break studentList$
    )
  ),
  filter((value) => value !== null),
  shareReplay(1) // No matter how many subscribers, as long as there's at least one subscriber, do all of the above exactly once and then emit the last value to any late subscribers just like a BehaviorSubject does
);

refreshStudentList(): void {
  this.studentListTrigger$.next();
}

现在,任何消费 studentList$ 的东西都会收到 last-emitted 结果,并且每次刷新都会得到一个新的学生列表。

基于 doc

中 BehaviorSubject 的定义

BehaviorSubject: A variant of Subject that requires an initial value and emits its current value whenever it is subscribed to

解决方案 1

为了快速解决,您可以在 getStudentsList 函数中 return Observable 之前设置 null:

  getStudentsList(params): Observable<StudentsListGrid> {
    if (this.studentListSubject$ === undefined) {
      this.studentListSubject$ = new BehaviorSubject<StudentListGrid>(null);
    }
    this.refetchStudentList(params);
    // add this line
    this.studentListSubject$.next(null);
    return this.studentListSubject$.asObservable().pipe(filter((value) => value !== null));
  }

原因是您通过传递 null 清空了 BehaviorSubject 的最后一个值,因此此函数的 return 始终 return 是一个新值。

解决方案 2

另一种方法(更好的方法)是使用 RxJs 库中的 distinctUntilChanged,我想你的名字在每次响应中都会变得不同:

 getStudentsList(params): Observable<StudentsListGrid> {
    if (this.studentListSubject$ === undefined) {
      this.studentListSubject$ = new BehaviorSubject<StudentListGrid>(null);
    }
    this.refetchStudentList(params);
    return this.studentListSubject$.asObservable().pipe(
             filter((value) => value !== null),
             distinctUntilChanged((prev, curr) => prev.name === curr.name));
  }

希望这个回答对您有所帮助。