簡體   English   中英

Rxjs:在 X 秒后使用 scan 或 mergeMap 或任何 rxjs 將 observables 數據流(grpc 服務)合並到一個數組中

[英]Rxjs: Combine observables data streams(grpc service) into an array after X secs using scan or mergeMap or any rxjs

我在 2 秒內收到來自服務(grpc)的響應數據流,例如 5 個流。 每個流都是我訂閱的可觀察對象。 收到每個流后的處理邏輯更多,每個流都有一些沉重的 json 對象,其中包含 base64 編碼的字節字符串,涉及 json 到復雜類型的轉換和更多條件邏輯。 因此,當一個流的處理邏輯完成時,我無法驗證其他流,因為它處理得非常快(接近並發)並被錯過。 所以我需要在監聽 X 秒后將所有這些 Y(例如 5)個流聚合到一個可觀察的數組中。 下面是代碼片段。

MyTestService.ts:

   @Injectable()
     export class MyTestService {    
            client: GrpcMyTestServiceClient;
            public readonly coreData$: Observable<TestReply.AsObject>;

  constructor(private readonly http: HttpClient) {
        this.client = new GrpcMyTestServiceClient(environment.apiProxyUri);
        this.coreData$ = this.listCoreStream();
    }

listCoreStream(): Observable<TestReply.AsObject> {    
    return new Observable(obs => {       
     const req = new SomeRequest(); 
     //Get stream data from service(grpc)
     const stream = this.client.getCoreUpdates(req);
 
     stream.on('data', (message: any) => {        
        obs.next(message.toObject() as TestReply.AsObject);
      });
    });
}

我的組件.ts

public testReply?: TestReply.AsObject;   
private _subscription: Subscription;
  constructor(private readonly _MyTestService: MyTestService) {     
  this._subscription = new Subscription();
}

  ngOnInit(): void {   
     this._subscription = this._MyTestService.coreData$.subscribe((data) => {
          if (data) {
                let obj = JSON.parse(data);
                //processing logic: condition checks, filtering based on child types,dynamic binding of styles, etc..
            }
        });
    }

由於數據在短時間內速度太快,不是所有的記錄或處理。 它看起來像在網絡世界中不可能的同步問題,滿足某些條件的最后一個流會覆蓋前一個流。 為了避免這種情況並一次處理所有流,我需要將所有流組合/合並到一個數組中,以便我可以在訂閱 observable 的組件內迭代它們中的每一個。 流數據排序無關緊要。

我試圖使用 rxjs 運算符,如timermergemapconcatmapscanmerge 但仍然是新手,無法弄清楚正確的方法。 下面是使用scan但無法獲得所需結果的一種此類嘗試,並且數組具有空值並且不確定如何從console.log使用該數組。 任何指針都會很有幫助,請提出建議。

解決辦法嘗試:

let temp: TestReply.AsObject[] = [];
let test = this._MyTestService.coreData$
  .pipe(
    mergeMap(_ => timer(5000)),
    scan<any>((allResponses, currentResponse) =>
      [...allResponses, currentResponse], this.temp),
  ).subscribe(console.log);

這是我的解決方案,使用訂閱中的下一個塊將所有數組推到一起,然后最終執行完整塊中的操作。

MyTestService.ts:

   @Injectable()
     export class MyTestService {    
            client: GrpcMyTestServiceClient;
            public readonly coreData$: Observable<TestReply.AsObject>;

  constructor(private readonly http: HttpClient) {
        this.client = new GrpcMyTestServiceClient(environment.apiProxyUri);
        this.coreData$ = this.listCoreStream();
    }

listCoreStream(): Observable<TestReply.AsObject> {    
    return new Observable(obs => {       
     const req = new SomeRequest(); 
     //Get stream data from service(grpc)
     const stream = this.client.getCoreUpdates(req);
 
     stream.on('data', (message: any) => {        
        obs.next(message.toObject() as TestReply.AsObject);
      });
    });

    stream.on('end', (message: any) => {        
        obs.complete();
      });
    });
}

我的組件.ts

public testReply?: TestReply.AsObject;   
public dataArray = [];
private _subscription: Subscription;
  constructor(private readonly _MyTestService: MyTestService) {     
  this._subscription = new Subscription();
}

  ngOnInit(): void {   
     this._subscription = this._MyTestService.coreData$.subscribe({
             next: (data) => {
                 if (data) {
                     this.dataArray.push(JSON.parse(data));
                 } 
             },
             complete: () => {
                // this.dataArray
                // above will be your final data
                // processing logic: condition checks, filtering based on child types,dynamic binding of styles, etc..
             })
  }

暫無
暫無

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

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