如何编写第一个 ngrx Effect 类

JerryWang_汪子熙 -
如何编写第一个 ngrx Effect 类

官网

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

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

一个可注入的 Actions 服务,它提供了在 reduce 最新状态后调度的所有操作的可观察流。

如下图所示:

使用 createEffect 函数将元数据附加到可观察流。 元数据用于注册订阅存储的流。从 effect 流返回的任何操作都会被分派回 Store。使用可管道化的 ofType 运算符过滤操作。 ofType 运算符将一种或多种操作类型作为参数来过滤要执行的操作。

如下图所示:

effects 订阅了 Store observable.服务被注入到效果中以与外部 API 交互并处理流。

看一个实际的 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的原创文章,尽在:"汪子熙":

特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

Tags 标签

angularjavascript前端html5node.js

扩展阅读

加个好友,技术交流

1628738909466805.jpg