[英]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 运算符,如timer
、 mergemap
、 concatmap
、 scan
、 merge
。 但仍然是新手,无法弄清楚正确的方法。 下面是使用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.