我正在写一个效果,该效果需要几个单独的服务调用(返回为可观察值)的结果才能完成。第一个服务调用必须在3个以上(可以是异步的)之前完成,然后再建立操作列表。我有它的工作,但感觉像是不必要的嵌套。
@Effect() loadMyData$: Observable<any> = this.actions$.pipe(
ofType(fromMyData.LOAD_DATA),
switchMap((action: fromMyData.Load) => {
return this.dataService.openMyData(action.payload).pipe(
switchMap(() => this.dataService.getShapes()),
switchMap(shapeData => {
return this.dataService.getCircles().pipe(
switchMap((circleData) => {
return this.dataService.getTriangles().pipe(
switchMap((triangleData) => {
const flatMyDataWithReferences: any = {
triangleName: triangleData.name,
shapeName: shapeData.name
};
return [
new fromShapes.Load(),
new fromBalls.Load(),
new fromCircles.LoadListSuccess(
this.organizeCircles(circleData)),
new fromMyData.LoadSuccess(flatMyDataWithReferences),
new fromUi.AddMessage({
type: MessageType.Success, message: 'Successfully loaded my data ' +
shapeData.name +
' from: ' + action.payload
})
];
}),
catchError((err) => this.myDataLoadErrorEvents(err))
);
}),
catchError((err) => this.myDataLoadErrorEvents(err))
);
}),
catchError((err) => this.myDataLoadErrorEvents(err))
);
}),
catchError((err) => this.myDataLoadErrorEvents(err))
);
基本上,在我的示例代码中,一旦我调用了dataService.openMyData
并从中返回,我想并行进行以下调用:
dataService.getShapes
dataService.getCircles
dataService.getTriangles
完成所有操作后,我想在我的操作数组中使用其返回的数据放入return [new etc...]
中以包装效果。
希望某人拥有比这丑陋(且不必要)的缩进方式更优雅的方式来处理3个中间服务调用...
我环顾四周,发现有些人正在使用forkJoin等待多个可观察对象的结果,但是看来他们不能使用该forkJoin可观察对象的结果作为操作的回报。例如,下面的代码告诉我,我最终并没有创建可观察的对象,而这正是我的效果所要求的。
@Effect() loadMyData$: Observable<any> = this.actions$.pipe(
ofType(fromMyData.LOAD_DATA),
switchMap((action: fromMyData.Load) => {
return this.dataService.openMyData(action.payload).pipe(
switchMap(() => {
return forkJoin(
this.dataService.getShapes(),
this.dataService.getCircles(),
this.dataService.getTriangles()
).pipe(
map(joinResult => {
const [shapeData, circleData, triangleData] = joinResult;
const flatMyDataWithReferences: any = {
triangleName: triangleData.name,
shapeName: shapeData.name
};
return [
new fromShapes.Load(),
new fromBalls.Load(),
new fromCircles.LoadListSuccess(
this.organizeCircles(circleData)),
new fromMyData.LoadSuccess(flatMyDataWithReferences),
new fromUi.AddMessage({
type: MessageType.Success, message: 'Successfully loaded my data ' +
shapeData.name +
' from: ' + action.payload
})
];
})
);
}),
catchError((err) => this.myDataLoadErrorEvents(err))
);
}),
catchError((err) => this.myDataLoadErrorEvents(err))
);
答案 0 :(得分:2)
使用forkJoin可以使用结果,而无需知道:
forkJoin(
this.dataService.getShapes(),
this.dataService.getCircles(),
this.dataService.getTriangles()
).pipe(
map(res => {
// Here you can use the result. That result is an array of last emitted value for each observable. The order is the same that you declare in observable array.
const [shapes, circles, triangles] = res;
})
);
要考虑的重要一件事是,如果请求之一失败,则您将不会收到任何值,应正确捕获它。
这里可以查看更多信息forkJoin
答案 1 :(得分:1)
forkJoin
等待多个可观察对象完成事实证明,我的问题需要两个重要的解决方案,以使其能够作为可观察的行为的正确流,这就是效果作为回报所需要的。第一部分是@llsanchez响应-使用return forkJoin().pipe(map(response => response.stuff));
形式以forkJoin
,pipe
和map
是正确的顺序来完成效果。
map
或mergeMap
返回效果中的可观察动作要使某件事情具有多个结果动作(在我的示例中具有此效果),才能正常工作,您必须将map
运算符替换为mergeMap
,如下所示:
@Effect() loadMyData$: Observable<any> = this.actions$.pipe(
ofType(fromMyData.LOAD_DATA),
switchMap((action: fromMyData.Load) => {
return this.dataService.openMyData(action.payload).pipe(
switchMap(() => {
return forkJoin(
this.dataService.getShapes(),
this.dataService.getCircles(),
this.dataService.getTriangles()
).pipe(
mergeMap(joinResult => {
const [shapeData, circleData, triangleData] = joinResult;
const flatMyDataWithReferences: any = {
triangleName: triangleData.name,
shapeName: shapeData.name
};
return [
new fromShapes.Load(),
new fromBalls.Load(),
new fromCircles.LoadListSuccess(
this.organizeCircles(circleData)),
new fromMyData.LoadSuccess(flatMyDataWithReferences),
new fromUi.AddMessage({
type: MessageType.Success, message: 'Successfully loaded my data ' +
shapeData.name +
' from: ' + action.payload
})
];
})
);
}),
catchError((err) => this.myDataLoadErrorEvents(err))
);
}),
catchError((err) => this.myDataLoadErrorEvents(err))
);
总而言之,要在效果中返回正确的操作流:
map
,格式如下:return forkJoin().pipe(map(response => response.action))
mergeMap
,格式如下:return forkJoin().pipe(mergeMap(response => [response.action1, response.action2]))