如何编写第一个 ngrx Effect 类

2021-11-22  本文已影响0人  _扫地僧_

官网

要将副作用与您的组件隔离,您必须创建一个 Effects 类来侦听事件并执行任务。

Effect 是具有不同部分的可注入服务类:

如下图所示:


如下图所示:


看一个实际的 effects 实现例子:

import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { EMPTY } from 'rxjs';
import { map, mergeMap, catchError } from 'rxjs/operators';
import { MoviesService } from './movies.service';

@Injectable()
export class MovieEffects {

  loadMovies$ = createEffect(() => this.actions$.pipe(
    ofType('[Movies Page] Load Movies'),
    mergeMap(() => this.moviesService.getAll()
      .pipe(
        map(movies => ({ type: '[Movies API] Movies Loaded Success', payload: movies })),
        catchError(() => EMPTY)
      ))
    )
  );

  constructor(
    private actions$: Actions,
    private moviesService: MoviesService
  ) {}
}

loadMovies$ 效果通过 Actions 流监听所有 dispatch 的 action,但只对使用 ofType 操作符的 [Movies Page] Load Movies 事件感兴趣。

我们必须使用 ofType 来过滤事件,应该通过构造函数依赖注入得到的 action 实例是一个单例,默认会捕捉到系统所有 dispatch 的事件。

然后使用 mergeMap 运算符将 action 流展平,并映射到新的可观察对象中。 MoviesService#getAll() 方法返回一个 observable,该 observable 将电影映射到成功的新 action,如果发生错误,当前返回一个空的 observable。

当需要更改状态时,action 被分派到 Store,在那里它可以由 reducer 处理。 在处理可观察流时处理错误也很重要,这样 effect 才能继续运行。

Registering root effects

编写 Effects 类后,必须注册它,以便效果开始运行。 要注册根级 effects,请将 EffectsModule.forRoot() 方法与您的 effect 数组添加到您的 AppModule。

下面是 app.module.ts 的例子:

import { EffectsModule } from '@ngrx/effects';
import { MovieEffects } from './effects/movie.effects';

@NgModule({
  imports: [
    EffectsModule.forRoot([MovieEffects])
  ],
})
export class AppModule {}

即使您没有注册任何根级效果,也必须将 EffectsModule.forRoot() 方法添加到您的 AppModule 导入中。

下面的代码来自 Spartacus 的 app.module.ts:

效果在 AppModule 加载后立即开始运行,以确保它们尽快侦听所有相关操作。

Registering feature effects

对于功能模块,通过在 NgModule 的导入数组中添加 EffectsModule.forFeature() 方法来注册你的 effect。

例子:

import { EffectsModule } from '@ngrx/effects';
import { MovieEffects } from './effects/movie.effects';

@NgModule({
  imports: [
    EffectsModule.forFeature([MovieEffects])
  ],
})
export class MovieModule {}

通过 forRoot() 或 forFeature() 多次运行效果类(例如通过不同的延迟加载模块)不会导致效果多次运行。 forRoot() 和 forFeature() 加载的效果之间没有功能差异; 函数之间的重要区别在于 forRoot() 设置 Effects 所需的 providers 程序。

更多Jerry的原创文章,尽在:"汪子熙":


上一篇下一篇

猜你喜欢

热点阅读