簡體   English   中英

RxJs - 組合兩個 observables,結果選擇器 function,zip

[英]RxJs - Combine two observables, result selector function, zip

我正在處理一些遺留代碼,並且設備狀態更新錯誤存在問題。 問題是,舊的 -舊版state 更新是使用長輪詢完成的,並且它在 BE 上存在無法修復的並發問題(BE 已棄用)。 有時它會忘記更新 state。 消息到達,但它不正確。

我可以檢索正確的 state 從新的 BE 請求它(該應用程序現在是一個令人討厭的混合體),但我無法正確地做到這一點。 我的第一個想法是使用whitLatestFrom ,但由於明顯的原因它不起作用。

legacyService.getState<LegacyState>()
  .pipe(
    subscribeOn(queue),
    withLatestFrom(this.realService.getRealStatus()), // request to the new BE
    map(([legacy, real]) => {
      // This if statement is a must. getRealStatus() returns only partial state, not the whole DeviceState
      // If there is a difference in the state from two sources, I create a new object with correct state
      if (legacy.state === DeviceState.INITIALIZED && !real.stable) {
        return new LegacyState(
          legacy.instrument, 
          legacy.db,
          DeviceState.UNSTABLE, 
        );
      }
      return event; // states are same, returning state from legacy source
    })
  )
  .subscribe(event => {
    this._deviceStateUpdated$.next(event);
  });

適用於應用程序重新啟動/重新加載,但后來real state 沒有更新,因為沒有進行新的調用,它只是返回以前的值。 combineLatest發生同樣的情況。 第一個(來自輪詢)被更新,第二個只是返回以前的值。

問題是:如何以這種方式組合兩個可觀察對象,當第一個被更新時,我也強制更新第二個可觀察對象的新值? 當然,我可以同時處理它們,因為第二個 observable 只返回部分 state。 我嘗試了多個地圖( swtichMap, concatMap, ... )但沒有成功。

我所說的投影 function 更准確地稱為結果選擇器 function。 請參閱本頁上的示例 3。 我將使用的基本結構是這樣的:

import { interval } from 'rxjs';
import { switchMap } from 'rxjs/operators';

//whatever your long polling interval is
const polling = interval(10000);

//then use that to collect your states 
const collectState = polling
    //pipe the interval event
   .pipe(
      //first you need the real state so you switchMap into that
      //I'm assuming this is Rx can treat as an observable, like a promise
      switchMap(this.realService.getRealStatus()),
      //then you have your real status and you need to use a result selector function
      switchMap(() => 
         legacyService.getState(),
         //at this point in the result selector function you have access to both states
         (real, legacy) => {
             //so you can apply your logic
             if (legacy.state === DeviceState.INITIALIZED && !real.stable) {
                 return new LegacyState(
                    legacy.instrument, 
                    legacy.db,
                    DeviceState.UNSTABLE
                );
             } else { return legacy }
      })
    );
  

我意識到我已經無濟於事地改變了真實/傳統的順序,但你明白了要點。

另一種方法是創建一個區間 observable 和一個 zipped observable,它們僅在真實狀態和遺留狀態都發出時才發出

import { zip, interval } from 'rxjs';
import { switchMap, map } from 'rxjs/operators';

const polling = interval(10000);
const states = zip(
    legacyService.getState(),
    this.realService.getRealStatus()
);
const collectState = polling
    .pipe(
        switchMap(states),
        map(statesArray => {
           //do the work here
        })
    );

);

希望這里有幫助

使用@Tom 的方法作為靈感,我能夠修復它。 盡管我直接在舊服務上而不是在輪詢間隔上通過管道switchMap ,但存在一個小的差異。

legacyService.getState<LegacyState>()
  .pipe(
    subscribeOn(queue),
    switchMap(() =>
      this.realService.getRealStatus(), // request to the new BE
      (legacy, real) => {
        if (legacy.state === DeviceState.INITIALIZED && !real.stable) {
          return new LegacyState(
            legacy.instrument, 
            legacy.db,
            DeviceState.UNSTABLE, 
          );
        }
        return event; // states are same, returning state from legacy source
      }
    )
  .subscribe(event => {
    this._deviceStateUpdated$.next(event);
  });

暫無
暫無

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

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