来自 ngrx 效果的多次 API 调用

Multiple API calls from ngrx effect

我是 ngrx store 和 redux 模式的新手。我在调度 updatePresentation$ 效果时遇到问题。调用 updatePresentation 操作时会调用效果。 updatePresentation 动作定义为:

    export const updatePresentation = createAction(
      '[Presentation] Update presentation',
      props<{ presentation: Presentation, files: FileList | null }>()
    );

updatePresentations$ 效果定义为:

    updatePresentations$ = createEffect(() => {
        return this.actions$
          .pipe(
            ofType(PresentationActions.updatePresentation),
            switchMap(action =>
              this.presentationService.updatePresentation(action.presentation)
                .pipe(
                  tap(presentation => {
                    if (action.files !== null && action.files.length > 0) {
                      this.store.dispatch(PresentationActions.fileUpload({presentationId: presentation.id, files: action.files}));
                    }
                  }),
                  map(presentation => PresentationActions.loadPresentations({pageable: new Pageable()})),
                  catchError(error => of(PresentationActions.updatePresentationFailure({error})))
                )
            )
          );
      });

基本上,我想做的是更新演示文稿,当演示文稿更新时,我想检查 action.files 是否存在,以及它是否调度 fileUpload 操作。在此之后,我想通过 returning loadPresentations 操作(将调用 loadPresentations$ 效果)再次加载演示文稿。这是 fileUpload$ 和 loadPresentations$ 效果的样子:

      loadPresentations$ = createEffect(() => {
        return this.actions$.pipe(
          ofType(PresentationActions.loadPresentations),
          concatMap(action => this.presentationService.getPresentations(action.pageable)
            .pipe(
              map(presentations => {
                this.store.dispatch(setLoadingSpinner({status: false}));
                return PresentationActions.loadPresentationsSuccess({page: presentations});
              }),
              catchError(error => of(PresentationActions.loadPresentationsFailure({error})))
            )
          )
        );
      });
      uploadFile$ = createEffect(() => {
        return this.actions$
          .pipe(
            ofType(PresentationActions.fileUpload),
            concatMap(action =>
              this.fileService.uploadFile(action.presentationId, action.files)
                .pipe(
                  map(bool => PresentationActions.loadPresentations({pageable: new Pageable()})),
                  catchError(error => of(PresentationActions.fileUploadFailure))
                )
            )
          );
      });

正如您在 updatePresentations$ 效果中看到的那样,我正在尝试 return 应该调用 loadPresentations$ 效果的 loadPresentations 操作,但是这不起作用,我想是因为我应该 return 和将由 reducer 解决的操作?我该怎么做?

您的操作不需要绑定到减速器。我们仅使用动作来触发效果,然后效果会使用 reducer 分派动作。所以这应该没问题。

你的效果还行,之前也说了,可能还有优化的地方。否则我没有看到任何可疑的东西

  updatePresentations$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(PresentationActions.updatePresentation),
      concatMap(action =>
        this.presentationService.updatePresentation(action.presentation).pipe(
          map(presentation => {
            // fileUpload dispatches loadPresentations anyway, is there a need to do it twice?
            if (action.files !== null && action.files.length > 0) {
              return PresentationActions.fileUpload({ presentationId: presentation.id, files: action.files });
            }
            return PresentationActions.loadPresentations({ pageable: new Pageable() });
          }),
          catchError(error => of(PresentationActions.updatePresentationFailure({ error })))
        )
      )
    );
  });

  uploadFile$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(PresentationActions.fileUpload),
      concatMap(action =>
        this.fileService.uploadFile(action.presentationId, action.files).pipe(
          map(bool => PresentationActions.loadPresentations({ pageable: new Pageable() })),
          catchError(error => of(PresentationActions.fileUploadFailure))
        )
      )
    );
  });

  loadPresentations$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(PresentationActions.loadPresentations),
      concatMap(action =>
        this.presentationService.getPresentations(action.pageable).pipe(
          // Use switch map to dispatch more actions at once
          swithcMap(presentations => [
            setLoadingSpinner({ status: false }),
            PresentationActions.loadPresentationsSuccess({ page: presentations }),
          ]),
          catchError(error => of(PresentationActions.loadPresentationsFailure({ error })))
        )
      )
    );
  });