action - NGRX - 对单一效果执行多个操作

标签 action effects ngrx

这就是我的效果..

@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/

相关文章:

c# - 无法从 'void' 转换为 'System.Action'

c++ - openFrameworks (C++) : Blur, Glow等经典效果

xcode - 在 Safari 中获取选定的文本并在操作扩展中使用它

c# - WPF窗口阴影效果

jquery - 如何使用 jQuery 为菜单添加悬停效果

javascript - combineLatest<{ [id : string]: Book }, string[]> 这是什么?

typescript - 类型 '{}' 不可分配给类型 'string'

javascript - Angular NgRx - 当其他操作返回值时调度一个有效的操作

c# - 常规方法的 Action/Func 扩展方法

forms - 如何在 JSF 中定义表单操作?