NgRx 如何按顺序调度 2 个操作

问题描述 投票:0回答:2

我似乎无法找到一种使用 NgRx(不是 RxJS 风格)的方法来在效果中调度 2 个操作。

我愿意(按此顺序):

  1. 删除数据库中带有效果的电影,
  2. 调度删除电影成功
  3. 调度 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?

ve also tried with switchMap and and flatMap, but never are both Actions dispatched correctly. I just can
似乎不明白,如何以迭代方式进行调度,但我确实需要它来满足我的特殊用例。

非常感谢任何帮助。

action ngrx dispatch
2个回答
4
投票

你不应该因为一个效果而分派两个动作。而是派遣某种成功的行动,然后在其他效果中对此做出反应。 请阅读此处

你可以创造连锁效应:

  1. 发送删除操作
  2. 删除调度deleteSuccess操作完成时
  3. 在deleteSuccess操作上触发loadMovies效果
  4. 在 loadMovies 成功时,为减速器拾取一些设置动作
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


1
投票

您可以使用

switchMap
运算符返回一组操作。

例如,代替;

    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)
        )
      )
    )
  );
© www.soinside.com 2019 - 2024. All rights reserved.