簡體   English   中英

修改 stream 中的數據 used with angular async pipe reactive way

[英]Modify data in stream used with angular async pipe reactive way

我正在嘗試使用異步管道而不是手動訂閱組件,以防萬一,我只是顯示我從服務器獲得的數據,一切正常。 但是,如果我以后需要根據某些事件更改顯示數據的顯示部分怎么辦?

例如,我有一個顯示時間表的組件,稍后可以被用戶接受。 我創建了 timesheet$ observable 並在我的模板中使用異步 pipe。為了接受我創建的主題,所以當用戶接受時間表時我可以發出。 但是我如何組合這兩個流(approvementChange$ 和 timesheet$),以便更新 $timesheet? 我正在嘗試 combineLatest,但它返回最新值,所以我無法決定來自 approvementChange stream 的值是新值還是舊值。 任何想法如何解決這個問題?

export class TimesheetComponent {
  errorMessage: string = '';
  timesheet$: Observable<Timesheet>;
  
  private approvementSubject = new Subject<TimesheetApprovement>();
  approvementChange$ = this.approvementSubject.asObservable();

  constructor(
    private planService: PlanService,
    private statusService: StatusService,
    private notifService: NotificationService
  ) {}

  this.timesheet$ = this.statusService.appStatus.pipe(
    switchMap((status) => {
      return this.planService.getTimesheet(
        status.selectedMonth,
        status.selectedAgency.agNum
      );
    })
  ); //get data every time user changed selected month

  approveTimesheet(isApproved: boolean = true) {
    const approvement: TimesheetApprovement = {
      isApproved: isApproved,
      approveTs: new Date(),
      isLock: true,
    };
    this.approvementSubject.next(approvement);
  }
}

您只需要跟蹤approvementChange

之后你可以通過withLatestFrom選擇最新的時間表

approvementChange$
.pipe(withLatestFrom(this.timesheet$))
.subscribe(([accepted, latestTimesheet]) => accepted ? save(latestTimesheet) : void 0)

但是,如果我以后需要根據某些事件更改顯示數據的顯示部分怎么辦?

RxJS 提供了許多用於合並、過濾和轉換可觀察對象的運算符。

您可以通過提供 function 來使用scan來維護“狀態”,該 function 接收先前的 state 和最新發射。

讓我們看一個使用通用Item接口的簡化示例:

interface Item {
  id         : number;
  name       : string;
  isComplete : boolean;
}

我們將使用 3 種不同的可觀察量:

  • initialItemState$ - 表示獲取后項目的初始 state
  • itemChanges$ - 代表對我們項目的修改
  • item$ - 每次應用更改時都會發出我們項目的 state
  private itemChanges$ = new Subject<Partial<Item>>();

  private initialItemState$ = this.itemId$.pipe(
    switchMap(id => this.getItem(id))
  );

  public item$ = this.initialItemState$.pipe(
    switchMap(initialItemState => this.itemChanges$.pipe(
      startWith(initialItemState),
      scan((item, changes) => ({...item, ...changes}), {} as Item),
    ))
  );

您可以看到我們通過將initialItemState$傳遞給itemChanges$ observable 來定義item$ 我們使用startWith將 initialItemState 發出到更改 stream 中。

所有的魔法都發生在scan內部,但設置非常簡單。 我們簡單地提供一個 function,它接受之前的 state 和新的變化,並返回該項目的更新后的 state。 在這種情況下,我只是天真地將更改應用於之前的 state;對於您的情況,此邏輯可能需要更復雜。

該解決方案是完全反應性的。 最終結果是一個干凈的item$ observable,每當 id 更改或項目發生更改時,它將發出當前項目的更新 state(基於 id)。

這是一個StackBlitz ,您可以在其中看到此行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM