ngrx ofType, @ ngrx / эффекты

Я пытаюсь понять, как эффекты 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 один раз выполнить !?

если он вызывается один раз, когда я отправляю действие, как эффекты узнают каждый раз, когда эффект ведьмы подписывается / выполняется?

Благодарим всех!


person Liam    schedule 03.08.2017    source источник
comment
youtube.com/watch?v=cyaAhXHhxgk, это может быть полезно   -  person Jota.Toledo    schedule 03.08.2017
comment
они объясняют, как использовать эффекты, а не как они работают под капотом. Я пытаюсь понять, как он кеширует тип действия, и подписывается ли он каждый раз, когда все эффекты эффектов, и найти тип действия   -  person Liam    schedule 04.08.2017


Ответы (4)


Вкратце, когда вызывается .ofType(), он подписывается на исходный поток действий и подталкивает соответствующие действия к результирующему потоку. Так оно и называется однажды.

Если мы посмотрим на исходный код , мы увидим, что под капотом ofType используется оператор filter библиотеки rxjs, что означает, что this.action$.ofType(CREATE_TASK) может быть расширен до

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

Описание того, как работает filter, можно найти в rxjs документах:

Подобно хорошо известному методу Array.prototype.filter, этот оператор принимает значения из исходного Observable, передает их через функцию predicate и выдает только те значения, которые дали true.

Стоит отметить, что каждый из ваших эффектов принимает наблюдаемое (this.action$) в качестве входных данных и возвращает новый наблюдаемый объект, который подписывается только один раз, когда эффекты инициализируются. Этот возвращаемый наблюдаемый определяет способ преобразования действий из входного наблюдаемого, но не влияет на сам исходный наблюдаемый.

В вашем примере метод ofType() возвращает новый наблюдаемый объект, который «слушает» this.action$ наблюдаемый объект и испускает только действия, удовлетворяющие условию action.type === CREATE_TASK. Затем следует оператор map, он также возвращает новый наблюдаемый объект, который «слушает» наблюдаемый объект, возвращаемый вызовом ofType(), и преобразует каждое действие, которое он получает, в новое значение в соответствии с переданной вами функцией проекции. Но все эти наблюдаемые объекты создаются только один раз при инициализации, и когда вы отправляете действия, они просто «проходят» через наблюдаемые объекты, фильтруются и преобразуются.

Вы также можете поближе познакомиться с rxjs. Я бы порекомендовал вам проверить доклад Андре Стальца, "Вы выучите RxJS", он должен дать вам интуитивное представление о том, что такое наблюдаемые и как они работают.

person Sergey Karavaev    schedule 07.08.2017
comment
спасибо за ответ, поэтому, если я использую store.dispatch ({type: CREAT_TASK, payload: payload}); каждый раз, когда я отправляю действие, this.action $ выполняет все эффекты (возвращается наблюдаемый) и проверяет (фильтрует), правильный ли тип? - person Liam; 07.08.2017
comment
Если у вас есть N эпики, каждый из которых использует .ofType(), то обычно предикат allowedTypes.some(type => type === action.type) будет выполняться N типов, что нормально, если у вас не зарегистрированы миллионы эпиков или переданы миллионы разрешенных типов действий (а я думаю, что это не так). Если фильтр не принимает действие, обратные вызовы связанных операторов (например, функция, которую вы передаете в map()) не будут выполняться. Я бы сказал, что вам не стоит беспокоиться о производительности ofType(), просто не создавайте миллионы эпиков :) - person Sergey Karavaev; 07.08.2017
comment
да, конечно, может быть, мне не переданы миллионы разрешенных типов действий, но для крупномасштабного приложения у нас есть 30 эпиков для модуля, любое маленькое действие, такое как (checkd / uncheckd), каждый раз, когда выполняются все эпики: \ я думаю, что они были можно сохранить тип как хэш и вызвать конкретный эпик, неважно, я не участник ngrx, так что .... :) - person Liam; 07.08.2017
comment
@SergeyKaravaev - извините, но что такое epic в этом контексте? - person ebhh2001; 13.09.2018
comment
@ ebhh2001, извините за путаницу, epic - это термин, используемый в redux-observable промежуточное ПО для redux. В ngrx-effects эпосах они называются эффектами. - person Sergey Karavaev; 14.09.2018

this.actions $ .ofType (CREATE_TASK) будет вызываться каждый раз, когда ваше действие будет отправлено, после выполнения вашего случая редуктора. как Redcucer

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

Сначала выполнится редуктор, а затем он будет действовать, если у вас есть какой-либо эффект, имеющий тип 'CREATE_TASK'. В шаблоне подписки все, что у вас есть, будет функцией обратного вызова и будет храниться в массиве под капотом в зависимости от условия. Когда вы отправляете действие на основе условия, что все функции будут вызывать тех, кто соответствует условию.

person viveksharma    schedule 23.07.2018

Дело в том, что ofType не экспортируется в класс Actions внутри ngrx / effects, поэтому вы можете использовать его следующим образом: 1- импорт ofType из ngrx / effects, который будет

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)))
      );
    })
  );
}
person shahrum hosseinabadi    schedule 14.01.2019

Вы также можете отправить набор действий из каждого эффекта.

Прочтите эту статью из средний

person Udi Mazor    schedule 27.10.2020