调用函数时清除 Observable 值

Clear Observable value when calling function

我有一个从服务中获取值的下拉列表。

下拉菜单

<mat-select
  *ngIf="selectedCloudTypeName === 'AWS'"
  class="select--width--130"
  [formControl]="awsOwnersControl"
  placeholder="AWS Owners"
  msInfiniteScroll
  (infiniteScroll)="loadMoreAwsOwners()"
  [complete]="currentAwsOwnerssDropdownOffset >= awsOwnersTotalCount"
>
  <mat-option *ngFor="let owner of awsOwners$ | async" [value]="owner.id">
    {{ owner.name }}
  </mat-option>
</mat-select>

TS 文件中的服务调用

getAwsOwners(offset = 0) {
this.isLoading$.next(true);
this.awsService
  .getOwnersListForAws(this.selectedCredentialIdForCloudType, this.selectedPlatform, { offset, limit: 100 })
  .subscribe(
    (owners: PaginatedResult<CommonEnumValue[]>) => {
      this.awsOwners.next(owners.data);
      this.awsOwnersTotalCount = owners.totalCount;
      this.isLoading$.next(false);
    },
    (error) => {
      this.isLoading$.next(false);
      this.alertify.error(error);
    },
  );

}

在 OnInit 钩子中我使用了一个 Observable

this.awsOwners$ = this.awsOwners.asObservable().pipe(scan((acc, curr) => [...acc, ...curr], []));

我在文件中声明为 属性 为

awsOwners = new BehaviorSubject<CommonEnumValue[]>([]);
awsOwners$: Observable<CommonEnumValue[]>;

问题是当我用不同的 'selectedPlatform' 值调用 getAwsOnwers 函数时,旧数据仍然存在,新数据被追加。

我试过像这样清除 awsOwners 主题

this.awsOwners.next([]);

在我调用它之前它确实清除了它并且新数据附加到旧数据,

有什么方法可以清除它吗?

我感觉到在扫描运算符中我需要清除“.acc”,因为它会累积值。

如果扫描 lambda 中的 curr 值为空,您可以重置扫描。

(acc, curr) => curr === [] ? [] : [...acc, ...curr]

但这对我来说有点脏。


一种更简洁的方法是在您希望重置后重新订阅您的 scan observable。

您可以创建一个 BehaviourSubject 并在每次您希望重置值时发出。 然后你可以将你的主题和 switchMap 传递给你的 scan observable。 这样,可观察对象将始终重新订阅您的扫描可观察对象,从而重新开始,因为如果源发出值,switchMap 会自动取消订阅和订阅。

可能看起来像这样:

BehaviourSubject resetSubject$ = new BehaviourSubject<void>(); // use behaviour subject to get an initial emit
awsOwners$ = resetSubject$.pipe(
  switchMap(() => this.awsOwners.asObservable().pipe(
    scan((acc, curr) => [...acc, ...curr], [])
  ),
);

// call this to reset your scan
resetSubject$.emit()
  1. this.awsOwners$ 管道中删除 scan
this.awsOwners$ = this.awsOwners.asObservable()
  1. this.selectedPlatform 作为主题,如果更改则使其调用 getAwsOwners
this._selectedPlatform$ = new Subject()

get selectedPlatform$() {
  // if platform is object you should provide comparing callback to distinctUntilChanged operator
  return this._selectedPlatform$.asObservable.pipe(distinctUntilChanged(), tap(() =>
    //make getAwsOwners() accept platform as an parameter and offset as a optional one.
    this.getAwsOwners(platform);
 ))
}
  1. getAwsOwners 订阅方法中进行一些更改
  .subscribe(
    (owners: PaginatedResult<CommonEnumValue[]>) => {
      // always if offset === 0 you should reset owners state
      this.awsOwners.next(offset ? 
        [...this.awsOwners.getValue(), ...owners.data] : 
        owners.data
      );

      this.awsOwnersTotalCount = owners.totalCount;
      this.isLoading$.next(false);
    },
    (error) => {
      this.isLoading$.next(false);
      this.alertify.error(error);
    },
  );

无需使用更新主题的方法,只需创建一个流来维护列表数据的状态(如果正在加载)和当前页面偏移量。

readonly offsetChangeSubject = new Subject<number>();
readonly selectedPlatformSubject = new Subject<string>();
readonly ownersList$ = this.selectedPlatformSubject.pipe(
  switchMap(platform) => offsetChangeSubject.pipe(
    startWith(0), 
    mergeScan((acc, offset) => 
      this.awsService.getOwnersListForAws(this.credentialId, platform, { offset, limit: 100 }).pipe(
        startWith({ ...acc, isLoading: true, offset })
        map(page => ({ 
          isLoading: false,
          offset,
          owners: owners.concat(page.data), 
          totalCount: page.totalCount 
        }))
      ),
      { isLoading: false, owners: [], totalCount: 0, offset }
    )
  ))
)
  1. 偏移量和平台参数转换为主题。
  2. 主观察对象是从平台主题创建的。
  3. 主要可观察对象中的唯一运算符是 switchMap。这会导致任何现有请求立即被取消。
  4. 在 switchMap 中,订阅了 offsetChanges。由于 startWith 运算符,它会立即发出 0。
  5. offsetChanges 的任何排放都将立即启动 mergeScan 内的所有者请求。这将使用之前发射的数据,并为每个请求发射两次,以便管理加载状态。

备注

  • 如果不明显,platformSubject 首次发出后总会有结果。

  • 我猜想一旦那个平台改变了,你也会想要重置偏移量,这就是我没有做的原因之一 offsetSubject 一个 BehaviorSubject 而不是使用 startWith 来发出 0. 所以你会从 ownersList$ observable 中检索偏移量的当前值,而不是 offsetChangeSubject - 那只是 更新。

  • 如果您希望当前列表状态不仅仅显示在视图中,您可以使用 shareReplay。