繁体   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