很抱歉,我想不出更好的标题。
我有这段代码,基本上是:
this.formGroup.valueChanges.pipe(
op.filter(v => !!v.cronExpressions),
op.map((v): string[] => v.cronExpressions),
op.map((v: string[]) => v.map(cron =>
this.cronService.getReadableForm(cron).pipe(
op.map(this.toDescription),
op.map((description): CronExpressionModel => ({ cron, description }))
)
)
),
// What now?
).subscribe((cronExpressions: CronExpressionModel[]) => ...) // Expected result
我想在subscribe()
上从所有服务调用返回的CronExpressionModel
数组。
我无法解决这个问题。
根据Martin的回答,当前的解决方案:
filter(v => !!v.cronExpressions),
map(v => v.cronExpressions),
map(cronExprs => cronExprs.map(c => this.invokeCronService(c))),
mergeMap(serviceCalls => forkJoin(serviceCalls).pipe(defaultIfEmpty([])))
答案 0 :(得分:2)
要将流转换为数组,可以使用toArray运算符。
这是一个建议:
this.formGroup.valueChanges.pipe(
filter(v => !!v.cronExpressions),
// transform [item1, item2...] into a stream ----item1----item2---->
concatMap((v): Observable<string> => from(v.cronExpressions).pipe(
// for each of the items, make a request and wait for it to respond
concatMap((cron: string) => this.cronService.getReadableForm(cron)),
map(this.toDescription),
map((description): CronExpressionModel => ({ cron, description })),
// wait for observables to complete. When all the requests are made,
// return an array containing all responses
toArray()
)
).subscribe((cronExpressions: CronExpressions[]) => ...) // Expected result
注意:
您可以使用mergeMap
而不是concatMap
来并行化请求。但是您需要知道自己在做什么;)
答案 1 :(得分:1)
如果您不介意并行运行所有请求,则只需添加forkJoin
:
switchMap(observables => forkJoin(...observables))
或者如果您想按顺序运行它们:
switchMap(observables => concat(...observables).pipe(toArray()))
根据您想要的行为,您可能希望使用switchMap
或concatMap
而不是mergeMap
。