这就是我的效果..
@Effect() uploadImages$ = this.actions$
.ofType(ProjectActions.UPLOAD_IMAGES)
.map(action => action.payload)
.flatMap(project => this.service.uploadImages(project))
.switchMap((project) => Observable.of(
this.imageActions.loadImages(),
this.projectActions.uploadImagesSuccess(project),
));
在 uploadImagesSuccess 触发之前尝试从 API 加载图像列表。
我尝试使用 .concatMap 和 .mergeMap 而不是 .switchMap,但事实似乎并非如此。
对效果和可观察对象来说相当新,从我所遇到的情况来看,没有任何东西能让我找到任何答案。
只需在另一个完成后触发一个即可。
编辑 1
因此,loadImages() 会触发,一旦完成 API 调用,它就会触发 loadImagesSuccess()。我想我的目标是......
@Effect() uploadImages$ = this.actions$
.ofType(ProjectActions.UPLOAD_IMAGES)
.map(action => action.payload)
.flatMap(project => this.service.uploadImages(project))
.switchMap((project) => Observable.of(
this.imageActions.loadImages(),
this.imageActions.loadImagesSuccess(),
this.projectActions.uploadImagesSuccess(project),
));
从更一般的意义上来说,我正在将照片保存到 API 上的项目中。我想在 uploadImagesSuccess() 有效负载到达我的选择器之前刷新我的 ImageState,并且由于 ImageState 未及时更新而具有未定义的图像路径。
编辑2
我通过这个解决方案使用 ForkJoin,https://github.com/ngrx/effects/issues/64
@Effect() uploadImages$ = this.actions$
.ofType(ProjectActions.UPLOAD_IMAGES)
.map(action => action.payload)
.flatMap(project => {
let projectInfo$ = this.projectService.uploadImages(project);
let imageInfo$ = this.imageService.loadImages();
return Observable.forkJoin(projectInfo$, imageInfo$);
})
.mergeMap((results: any[]) => {
let myActions: any[] = [];
let actionGenerators = [
(data: any) => {
return this.projectActions.uploadImagesSuccess(data);
},
(data: any) => {
return this.imageActions.loadImagesSuccess(data);
}
];
results.forEach((data: any, index: number) => {
myActions.push(actionGenerators[index](data));
});
return Observable.from(myActions);
});
不确定这是否是解决此问题的最佳方法,但只要我延迟加载图像的 API 调用,它就可以工作。如果没有延迟,图像将在保存新图像之前加载。目前我正在 API 端延迟 loadImages()。
如果可能的话,我想要一种更好的方法来处理将 API 调用发送到 imageService.loadImages() 直到 projectService.uploadImages() 返回。然后,一旦返回所有数据,就触发更新存储的操作。
建议使用 concat 而不是 forkJoin,以便等待一个 API 调用完成后再继续下一个。但这会破坏 results.Foreach(),因为结果不再位于数组中。
最佳答案
也许你可以试试这个。无需使用加载图像操作,只需在上传图像副作用中执行加载图像 api 调用即可。像这样的事情:
@Effect() uploadImages$ = this.actions$
.ofType(ProjectActions.UPLOAD_IMAGES)
.map(action => action.payload)
.mergeMap(project => this.service.uploadImages(project)
.mergeMap(() => {
return this.otherService.loadImages()
.map((images) => this.projectActions.uploadImagesSuccess({ project: project, images: images))
}
));
然后您可以通过监听 UPLOAD_IMAGES_SUCCESS 操作来让两个 reducer 更新状态:
export default function ProjectReducer (state = initialState, action: Action) {
switch (action.type) {
case UPLOAD_IMAGES_SUCCESS:
return // do your update with action.payload.project
default:
return state;
}
};
export default function ImagesReducer (state = initialState, action: Action) {
switch (action.type) {
case UPLOAD_IMAGES_SUCCESS:
return // do your update with action.payload.images
default:
return state;
}
};
您可以在 ngrx 示例应用程序中看到相同的模式。在两个 reducer 中,ADD_TO_CART 正在被监听:
https://github.com/btroncone/ngrx-examples/blob/master/shopping-cart/src/app/reducers/products.ts
https://github.com/btroncone/ngrx-examples/blob/master/shopping-cart/src/app/reducers/cart.ts
关于action - NGRX - 对单一效果执行多个操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45292974/