NgRx Effects 使用无限循环使 Angular 应用程序崩溃
NgRx Effects crashing Angular app with infinite loop
我是 NGRx 的新手,我正在尝试在我的小项目上使用 Effects,因为日期使用外部数据我决定将其放入效果中,所以应用程序现在在 运行 后因无限循环而崩溃“npm start”,它只是停止工作。这是 link 回购 Github Repo
count.effects.ts
import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import {
countActionsType,
CountUpdatedAtAction,
} from './reducers/count/count.actions';
import { map } from 'rxjs/operators';
@Injectable()
export class AppEffects {
constructor(private actions$: Actions) {}
@Effect()
updatedAt$() {
return this.actions$.pipe(
ofType(
countActionsType.increase,
countActionsType.decrease,
countActionsType.clear,
countActionsType.updatedAt
),
map(() => {
return new CountUpdatedAtAction({
updatedAt: Date.now(),
});
})
);
}
}
count.reducer.ts
import { CountActions, countActionsType } from './count.actions';
export const COUNT_NODE = 'count';
export interface ICountState {
count: number;
updatedAt: number;
}
const initialState: ICountState = {
count: 0,
updatedAt: Date.now(),
};
export const countReducer = (state = initialState, actions: CountActions) => {
switch (actions.type) {
case countActionsType.increase:
return {
...state,
count: state.count + 1,
};
case countActionsType.decrease:
return {
...state,
count: state.count - 1,
};
case countActionsType.clear:
return {
...state,
count: 0,
};
case countActionsType.updatedAt:
return {
...state,
updatedAt: actions.payload.updatedAt,
};
default:
return state;
}
};
count.actions.ts
import { Action } from '@ngrx/store';
export enum countActionsType {
increase = '[COUNT] increase',
decrease = '[COUNT] decrease',
clear = '[COUNT] clear',
updatedAt = '[COUNT] updated at',
}
export class CountIncreaseAction implements Action {
readonly type = countActionsType.increase;
}
export class CountDecreaseAction implements Action {
readonly type = countActionsType.decrease;
}
export class CountClearAction implements Action {
readonly type = countActionsType.clear;
}
export class CountUpdatedAtAction implements Action {
readonly type = countActionsType.updatedAt;
constructor(
public payload: {
updatedAt: number;
}
) {}
}
export type CountActions =
| CountIncreaseAction
| CountDecreaseAction
| CountClearAction
| CountUpdatedAtAction;
count.components.ts
import { Component } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { ICountState } from './reducers/count/count.reducer';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { selectCount, selectUpdatedAt } from './reducers/count/count.selectors';
import {
CountIncreaseAction,
CountDecreaseAction,
CountClearAction,
} from './reducers/count/count.actions';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
public count$: Observable<number> = this.store$.pipe(select(selectCount));
public isButtonDisabled$: Observable<boolean> = this.count$.pipe(
map((count) => count <= 0)
);
public updatedAt$: Observable<number> = this.store$.pipe(
select(selectUpdatedAt)
);
constructor(private store$: Store<ICountState>) {}
increase() {
this.store$.dispatch(new CountIncreaseAction());
}
decrease() {
this.store$.dispatch(new CountDecreaseAction());
}
clear() {
this.store$.dispatch(new CountClearAction());
}
}
这很简单,当你发送一些动作时你的效果就会被触发,包括countActionsType.updatedAt
。
在你的效果中,你发送了一个名为 CountUpdatedAtAction
的 Action,其类型为 countActionsType.updatedAt
.
那是你的无限循环:)
每次更新,效果都会尝试更新,再更新,再更新:P
要完成这项工作,只需删除 countActionsType.updatedAt
中的:
ofType(
countActionsType.increase,
countActionsType.decrease,
countActionsType.clear,
countActionsType.updatedAt // <--- remove this
),
我是 NGRx 的新手,我正在尝试在我的小项目上使用 Effects,因为日期使用外部数据我决定将其放入效果中,所以应用程序现在在 运行 后因无限循环而崩溃“npm start”,它只是停止工作。这是 link 回购 Github Repo
count.effects.ts
import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import {
countActionsType,
CountUpdatedAtAction,
} from './reducers/count/count.actions';
import { map } from 'rxjs/operators';
@Injectable()
export class AppEffects {
constructor(private actions$: Actions) {}
@Effect()
updatedAt$() {
return this.actions$.pipe(
ofType(
countActionsType.increase,
countActionsType.decrease,
countActionsType.clear,
countActionsType.updatedAt
),
map(() => {
return new CountUpdatedAtAction({
updatedAt: Date.now(),
});
})
);
}
}
count.reducer.ts
import { CountActions, countActionsType } from './count.actions';
export const COUNT_NODE = 'count';
export interface ICountState {
count: number;
updatedAt: number;
}
const initialState: ICountState = {
count: 0,
updatedAt: Date.now(),
};
export const countReducer = (state = initialState, actions: CountActions) => {
switch (actions.type) {
case countActionsType.increase:
return {
...state,
count: state.count + 1,
};
case countActionsType.decrease:
return {
...state,
count: state.count - 1,
};
case countActionsType.clear:
return {
...state,
count: 0,
};
case countActionsType.updatedAt:
return {
...state,
updatedAt: actions.payload.updatedAt,
};
default:
return state;
}
};
count.actions.ts
import { Action } from '@ngrx/store';
export enum countActionsType {
increase = '[COUNT] increase',
decrease = '[COUNT] decrease',
clear = '[COUNT] clear',
updatedAt = '[COUNT] updated at',
}
export class CountIncreaseAction implements Action {
readonly type = countActionsType.increase;
}
export class CountDecreaseAction implements Action {
readonly type = countActionsType.decrease;
}
export class CountClearAction implements Action {
readonly type = countActionsType.clear;
}
export class CountUpdatedAtAction implements Action {
readonly type = countActionsType.updatedAt;
constructor(
public payload: {
updatedAt: number;
}
) {}
}
export type CountActions =
| CountIncreaseAction
| CountDecreaseAction
| CountClearAction
| CountUpdatedAtAction;
count.components.ts
import { Component } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { ICountState } from './reducers/count/count.reducer';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { selectCount, selectUpdatedAt } from './reducers/count/count.selectors';
import {
CountIncreaseAction,
CountDecreaseAction,
CountClearAction,
} from './reducers/count/count.actions';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
public count$: Observable<number> = this.store$.pipe(select(selectCount));
public isButtonDisabled$: Observable<boolean> = this.count$.pipe(
map((count) => count <= 0)
);
public updatedAt$: Observable<number> = this.store$.pipe(
select(selectUpdatedAt)
);
constructor(private store$: Store<ICountState>) {}
increase() {
this.store$.dispatch(new CountIncreaseAction());
}
decrease() {
this.store$.dispatch(new CountDecreaseAction());
}
clear() {
this.store$.dispatch(new CountClearAction());
}
}
这很简单,当你发送一些动作时你的效果就会被触发,包括countActionsType.updatedAt
。
在你的效果中,你发送了一个名为 CountUpdatedAtAction
的 Action,其类型为 countActionsType.updatedAt
.
那是你的无限循环:)
每次更新,效果都会尝试更新,再更新,再更新:P
要完成这项工作,只需删除 countActionsType.updatedAt
中的:
ofType(
countActionsType.increase,
countActionsType.decrease,
countActionsType.clear,
countActionsType.updatedAt // <--- remove this
),