美文网首页
如何编写第一个 ngrx Effect 类

如何编写第一个 ngrx Effect 类

作者: _扫地僧_ | 来源:发表于2021-11-22 12:09 被阅读0次

    官网

    要将副作用与您的组件隔离,您必须创建一个 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的原创文章,尽在:"汪子熙":


    相关文章

      网友评论

          本文标题:如何编写第一个 ngrx Effect 类

          本文链接:https://www.haomeiwen.com/subject/fortaltx.html