【问题标题】:ngrx ofType, @ngrx/effectsngrx ofType,@ngrx/效果
【发布时间】:2018-01-11 10:08:05
【问题描述】:

我试图了解 typeof 效果在 ngrx 的底层是如何工作的, 如果我在我的应用模块中声明:

....

@NgModule({
    imports: [
        EffectsModule.forRoot([TodosEffectsService])
],

....

而且我肯定会写效果文件:

@Effect() createTodos$ = this.actions$
.ofType(CREATE_TASK)
    .map(() => {
        console.log('called');
            return { type: 'OTHER'};
});

@Effect() addTodos$ = this.actions$
.ofType(CREATE_TASK)
    .map(() => {
        console.log('called');
            return { type: 'OTHER'};
});

我试着理解,现在在运行时我调度一个动作 this.action$ 被订阅并且每次都执行 ofType 来匹配类型? 或 ofType 一次执行!?

如果它调用一次,当我调度动作时,效果如何知道每次女巫效果订阅/执行?

谢谢大家!

【问题讨论】:

  • youtube.com/watch?v=cyaAhXHhxgk 这可能会有所帮助
  • 他们解释了如何使用效果,而不是它如何在幕后工作。我试图了解它是如何缓存动作类型的,以及它是否每次都订阅所有效果动作并找到动作类型

标签: angular typescript ngrx ngrx-effects


【解决方案1】:

您还可以从每个效果中分派一组动作。

Read this article from medium

【讨论】:

    【解决方案2】:

    关键是在ngrx/effects里面的Actions类没有导出ofType 所以你可以像下面这样使用它: 1- 从ngrx/effects 导入ofType

    import { Injectable } from "@angular/core";
    
    import { Effect, Actions, ofType } from "@ngrx/effects";
    import * as omid from "@ngrx/effects";
    import { of } from "rxjs";
    import { map, switchMap, catchError } from "rxjs/operators";
    @Injectable()
    export class PizzasEffects {
      constructor(
        private actions$: Actions,
        private pizzaService: frtomServices.PizzasService
      ) {}
    
      @Effect()
      LoadPizzas$ = this.actions$.pipe(
        ofType(pizzaActions.LOAD_PIZZAS),
        switchMap(() => {
          return this.pizzaService.getPizzas().pipe(
            map(pizzas => new pizzaActions.LoadPizzasSuccess(pizzas)),
            catchError(error => of(new pizzaActions.LoadPizzasFail(error)))
          );
        })
      );
    }
    

    【讨论】:

      【解决方案3】:

      this.actions$ .ofType(CREATE_TASK) 将在每次调度您的操作时调用,在您的减速器案例执行后。 喜欢 减速机

      switch(action) {
      case youractionsname.CREATE_TASK : {
      // pure function logic here
         }
      }
      

      如果你有任何类型为“CREATE_TASK”的效果,第一个减速器将执行,然后它会生效。 在订阅模式中,您订阅的任何内容都将是回调函数,它将根据条件存储在引擎盖下的数组中。当您根据条件调度动作时,所有函数都会调用满足条件的人。

      【讨论】:

        【解决方案4】:

        简而言之,当.ofType() 被调用时,它订阅动作的源流并将匹配的动作推送到结果流。所以它确实被调用了一次。

        如果我们查看source code,我们会看到ofType 使用filter 库的filter 运算符,这意味着this.action$.ofType(CREATE_TASK) 可以扩展为

        this.action$.filter(action => action.type === CREATE_TASK)
        

        filter如何工作的描述可以从rxjsdocs找到:

        与众所周知的Array.prototype.filter 方法类似,此运算符从源 Observable 获取值,将它们传递给 predicate 函数,并且只发出产生 true 的值。

        值得注意的是,您的每个效果都将一个可观察对象 (this.action$) 作为输入,并在初始化效果时返回一个仅订阅一次的新可观察对象。返回的 observable 定义了输入 observable 中的动作如何转换的方式,但它不影响源 observable 本身。

        在您的示例中,ofType() 方法返回一个新的 observable,它“侦听”this.action$ observable,并且只发出满足条件 action.type === CREATE_TASK 的操作。然后是 map 运算符,它还返回一个新的 observable,它“侦听”ofType() 调用返回的 observable,并根据您传递的投影函数将接收到的每个操作转换为新值。但是所有这些可观察对象都只创建一次,在初始化时,当您调度操作时,它们只是“流动”通过可观察对象,被过滤和转换。

        您可能还想更加熟悉rxjs。我建议您查看 André Staltz 的 "You will learn RxJS" 演讲,它应该让您直观地了解什么是可观察对象以及它们是如何工作的。

        【讨论】:

        • 感谢您的回复,所以如果我使用 store.dispatch({ type: CREAT_TASK, payload: payload});每次我调度一个动作时,this.action$ 都会执行所有效果(返回 observable)并检查(过滤)类型是否正确?
        • 如果你有 N 史诗,每个都使用 .ofType(),那么通常谓词 allowedTypes.some(type => type === action.type) 将被执行 N 类型,这很好,除非你有数百万个史诗注册或通过了数百万个允许的操作类型(我猜不是这样)。如果过滤器不接受操作,则不会执行链式操作符的回调(例如,您传递给map() 的函数)。我会说你不应该关心ofType() 的表现,只是不要创造数百万的史诗:)
        • 是的,当然,也许我没有通过数百万个允许的动作类型,但对于大规模应用,我们有 30 个用于模块的史诗,任何小动作,例如(选中/未选中)每次都执行的史诗:\我认为他们可以将类型保存为哈希并调用特定的史诗没关系,我不是ngrx贡献者,所以.... :)
        • @SergeyKaravaev - 抱歉,在这种情况下 epic 是什么?
        • @ebhh2001,很抱歉造成混淆,epic 是用于 redux 的 redux-observable 中间件中的术语。在ngrx-effects 史诗中被称为“效果”。
        猜你喜欢
        • 2019-10-13
        • 1970-01-01
        • 2019-07-02
        • 2020-03-18
        • 2021-08-30
        • 1970-01-01
        • 1970-01-01
        • 2018-10-29
        • 2019-02-12
        相关资源
        最近更新 更多