在 ngrx/effects 中不调度操作时卡在无限循环中
Stuck in endless loop when not dispatching an action in ngrx/effects
我正在使用 Angular2 以及 ngrx/store 和 ngrx/effects 进行状态管理。
当某个操作失败时,我想显示一条错误消息,但似乎我无法在 @Effects()
块中执行此任务。请参阅以下内容:
@Effect() selectOfficeFail$ = this.actions$
.ofType(SelectOfficeActions.LOAD_FAIL)
.do(() => {
alert('Error! No offices found!'); // I keep entering here
});
当上面的代码 运行 时,警报会 运行 无数次,直到浏览器崩溃。似乎 @Effect()
必须 return 一个新的 dispatch()
但我不明白为什么。为什么上面的 alert() 运行 无数次?
编辑:我不是调度SelectOfficeActions.LOAD_FAIL
多次。只有一次
是的,您是对的,@effect
需要分派新操作,但我认为您的应用程序逻辑有问题。
您不应在组件或服务中调度 SelectOfficeActions.LOAD_FAIL
操作,而应调度调用 @Effect
的 LOAD 操作,然后效果会调度 LOAD_COMPLETE
或 LOAD_FAIL
根据标准。
类似这样的东西 example 来自图书馆 github
@Effect() login$ = this.updates$
// Listen for the 'LOGIN' action
.whenAction('LOGIN')
// Map the payload into JSON to use as the request body
.map(update => JSON.stringify(update.action.payload))
.switchMap(payload => this.http.post('/auth', payload)
// If successful, dispatch success action with result
.map(res => ({ type: 'LOGIN_SUCCESS', payload: res.json() }))
// If request fails, dispatch failed action
.catch(() => Observable.of({ type: 'LOGIN_FAILED' }));
);
问题是 do
允许动作流经您的效果,然后动作再次由商店调度。您可以使用 filter
来防止这种情况发生:
@Effect() selectOfficeFail$ = this.actions$
.ofType(SelectOfficeActions.LOAD_FAIL)
.do(() => {
alert('Error! No offices found!'); // I keep entering here
})
.filter(() => false);
[更新]
现在最好的方法是使用 dispatch
选项,如下所示:
@Effect({dispatch: false}) selectOfficeFail$ = this.actions$
.ofType(SelectOfficeActions.LOAD_FAIL)
.do(() => {
alert('Error! No offices found!'); // I keep entering here
});
表示"reacts to this action but don't send another".
如果使用 createEffect
函数,则需要将 dispatch: false
标志作为配置参数传递 (ngrx.io reference)
effectName$ = createEffect(
() => this.actions$.pipe(
ofType(FeatureActions.actionOne),
tap(() => console.log('Action One Dispatched'))
),
{ dispatch: false }
// FeatureActions.actionOne is not dispatched
);
我正在使用 Angular2 以及 ngrx/store 和 ngrx/effects 进行状态管理。
当某个操作失败时,我想显示一条错误消息,但似乎我无法在 @Effects()
块中执行此任务。请参阅以下内容:
@Effect() selectOfficeFail$ = this.actions$
.ofType(SelectOfficeActions.LOAD_FAIL)
.do(() => {
alert('Error! No offices found!'); // I keep entering here
});
当上面的代码 运行 时,警报会 运行 无数次,直到浏览器崩溃。似乎 @Effect()
必须 return 一个新的 dispatch()
但我不明白为什么。为什么上面的 alert() 运行 无数次?
编辑:我不是调度SelectOfficeActions.LOAD_FAIL
多次。只有一次
是的,您是对的,@effect
需要分派新操作,但我认为您的应用程序逻辑有问题。
您不应在组件或服务中调度 SelectOfficeActions.LOAD_FAIL
操作,而应调度调用 @Effect
的 LOAD 操作,然后效果会调度 LOAD_COMPLETE
或 LOAD_FAIL
根据标准。
类似这样的东西 example 来自图书馆 github
@Effect() login$ = this.updates$
// Listen for the 'LOGIN' action
.whenAction('LOGIN')
// Map the payload into JSON to use as the request body
.map(update => JSON.stringify(update.action.payload))
.switchMap(payload => this.http.post('/auth', payload)
// If successful, dispatch success action with result
.map(res => ({ type: 'LOGIN_SUCCESS', payload: res.json() }))
// If request fails, dispatch failed action
.catch(() => Observable.of({ type: 'LOGIN_FAILED' }));
);
问题是 do
允许动作流经您的效果,然后动作再次由商店调度。您可以使用 filter
来防止这种情况发生:
@Effect() selectOfficeFail$ = this.actions$
.ofType(SelectOfficeActions.LOAD_FAIL)
.do(() => {
alert('Error! No offices found!'); // I keep entering here
})
.filter(() => false);
[更新]
现在最好的方法是使用 dispatch
选项,如下所示:
@Effect({dispatch: false}) selectOfficeFail$ = this.actions$
.ofType(SelectOfficeActions.LOAD_FAIL)
.do(() => {
alert('Error! No offices found!'); // I keep entering here
});
表示"reacts to this action but don't send another".
如果使用 createEffect
函数,则需要将 dispatch: false
标志作为配置参数传递 (ngrx.io reference)
effectName$ = createEffect(
() => this.actions$.pipe(
ofType(FeatureActions.actionOne),
tap(() => console.log('Action One Dispatched'))
),
{ dispatch: false }
// FeatureActions.actionOne is not dispatched
);