NgRx 如何按顺序分派 2 个动作

NgRx how to dispatch 2 actions in order

我似乎无法找到一种使用 NgRx(不是 RxJS 样式)的方法来在一个效果中分派 2 个 Actions。

我想(按此顺序):

  1. 删除数据库中带有效果的电影,
  2. 调度 deleteMovieSuccess
  3. dispatch getMovies(之后我需要重新加载所有电影!

我试着像下面那样做,但它只触发了第一个动作,我看不到另一个动作: 在我的日志中我可以看到:

我有以下操作:

export const getMovies = createAction('[Movie List] Get Movies', props<{search: string, page: number, limit: number}>());
export const getMoviesSuccess = createAction('[Movies List] Get Movies Success', props<{ search: string, page: number, limit: number }>());

export const deleteMovie = createAction('[Movie List] Remove Movie', props<{ movieToDelete: Movie, search: string, page: number, limit: number }>());
export const deleteMovieSuccess = createAction('[Movie List] Remove Movie Success', props<{ movieToDelete: Movie }>());

以及以下效果:

    deleteMovie$ = createEffect(() => this.actions$.pipe(
      ofType(MovieActions.deleteMovie),
      mergeMap(({movieToDelete, search, page, limit}) =>
        this.moviesService.deleteMovie(movieToDelete)
        .pipe(
          map(() => MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete})),
          map(() => MovieActions.getMovies({search, page, limit})),
          catchError(() => EMPTY)
        )
      )
    )
  );

如何按此顺序触发 BOTH、deleteMoviesSuccess 和 getMovies?

我也尝试过使用 switchMap 和 faltMap,但从来没有正确调度过两个 Action。 我似乎无法理解,如何以迭代方式进行调度,但我的特殊用例确实需要它。

非常感谢任何帮助。

您可以使用 switchMap 运算符来 return 一组操作。

例如,而不是;

    deleteMovie$ = createEffect(() => this.actions$.pipe(
      ofType(MovieActions.deleteMovie),
      mergeMap(({movieToDelete, search, page, limit}) =>
        this.moviesService.deleteMovie(movieToDelete)
        .pipe(
          map(() => MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete})),
          map(() => MovieActions.getMovies({search, page, limit})),
          catchError(() => EMPTY)
        )
      )
    )
  );

你可以试试;

    deleteMovie$ = createEffect(() => this.actions$.pipe(
      ofType(MovieActions.deleteMovie),
      mergeMap(({movieToDelete, search, page, limit}) =>
        this.moviesService.deleteMovie(movieToDelete)
        .pipe(
          switchMap(() => [MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete}), 
MovieActions.getMovies({search, page, limit})]),
          catchError(() => EMPTY)
        )
      )
    )
  );

你不应该因为一个效果而分派两个动作。而是发送某种成功动作,然后在其他效果中对此做出反应。 Read here

您可以创建连锁效应:

  1. 调度删除操作
  2. 删除调度 deleteSuccess 操作完成时
  3. deleteSuccess 操作触发 loadMovies 效果
  4. 在 loadMovies 成功时,reducer 会执行一些设置操作
deleteMovie$ = createEffect(() => this.actions$.pipe(
    ofType(MovieActions.deleteMovie),
    mergeMap(({movieToDelete, search, page, limit}) => this.moviesService.deleteMovie(movieToDelete).pipe(
        map(() => MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete})),
        catchError(() => EMPTY)
    ))
));

loadMovie$ = createEffect(() => this.actions$.pipe(
    ofType(MovieActions.deleteMovieSuccess),
    mergeMap(() => this.moviesService.loadMovies().pipe(
         map(movies => MovieActions.setMovies({ movies })),
         catchError(() => EMPTY)
    ))
));

编辑
此外,您可以将这些参数保存在商店中,而不是传递限制或搜索等参数。这样做可以让您在需要时始终访问那些有效的内容。 NgRx 文档有一个很好的例子,说明如何在效果中进行选择。 ngrx.io/api/effects/concatLatestFrom