我遇到的问题是ngrx商店没有向应该处理的效果发送动作。
以下是尝试发送的组件:
signin() {
this.formStatus.submitted = true;
if (this.formStatus.form.valid) {
this.store.dispatch(new StandardSigninAction(this.formStatus.form.value.credentials));
}
}
行动:
export const ActionTypes = {
STANDARD_SIGNIN: type('[Session] Standard Signin'),
LOAD_PERSONAL_INFO: type('[Session] Load Personal Info'),
LOAD_USER_ACCOUNT: type('[Session] Load User Account'),
RELOAD_PERSONAL_INFO: type('[Session] Reload Personal Info'),
CLEAR_USER_ACCOUNT: type('[Session] Clear User Account')
};
export class StandardSigninAction implements Action {
type = ActionTypes.STANDARD_SIGNIN;
constructor(public payload: Credentials) {
}
}
...
export type Actions
= StandardSigninAction
| LoadPersonalInfoAction
| ClearUserAccountAction
| ReloadPersonalInfoAction
| LoadUserAccountAction;
效果:
@Effect()
standardSignin$: Observable<Action> = this.actions$
.ofType(session.ActionTypes.STANDARD_SIGNIN)
.map((action: StandardSigninAction) => action.payload)
.switchMap((credentials: Credentials) =>
this.sessionSigninService.signin(credentials)
.map(sessionToken => {
return new LoadPersonalInfoAction(sessionToken);
})
);
我可以在调试中看到该组件确实调用了dispatch方法。我还可以确认StandardSigninAction
确实是实例化的,因为构造函数中的断点被命中了。
但standardSignin$
效果未被调用......
什么可能导致效果不被调用?
如何调试商店内发生的事情?
有人可以帮忙吗?
P.S。我在我的导入中运行以下效果:
EffectsModule.run(SessionEffects),
编辑:这是我的SessionSigninService.signin方法(确实返回一个Observable)
signin(credentials: Credentials) {
const headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'});
const options = new RequestOptions({headers: headers});
const body = 'username=' + credentials.username + '&password=' + credentials.password;
return this.http.post(this.urls.AUTHENTICATION.SIGNIN, body, options).map(res => res.headers.get('x-auth-token'));
}
答案 0 :(得分:15)
这不是一个明确的答案,但是,希望它会有所帮助。
开始之前:
@ngrx
软件包(适用于您正在使用的Angular版本)。如果你还没有这样做,你应该看看the implementation of the Store
- 这样你就可能出现的问题做了一些有根据的猜测。请注意,Store
非常轻松。它既是一个可观察的(使用国家作为其来源),也是一个观察者(顺从调度员)。
如果你看store.dispatch
,你就会发现它是别名
store.next
,在Dispatcher
上调用next
。
所以打电话:
this.store.dispatch(new StandardSigninAction(this.formStatus.form.value.credentials));
应该只看到调度员发出的动作。
注入效果的Actions
可观察物也非常清晰。它只是一个使用Dispatcher
作为其来源的可观察对象。
要查看流经效果的动作,您可以将其替换为:
@Effect()
standardSignin$: Observable<Action> = this.actions$
.ofType(session.ActionTypes.STANDARD_SIGNIN)
用这个:
@Effect()
standardSignin$: Observable<Action> = this.actions$
.do((action) => console.log(`Received ${action.type}`))
.filter((action) => action.type === session.ActionTypes.STANDARD_SIGNIN)
ofType
不是运营商;它是一种方法,因此要添加基于do
的日志记录,需要将其替换为filter
。
登录到位后,如果您收到动作,效果的实现就会出现问题(或者动作类型&#39;字符串/常量不是您认为的那样而且有些东西不匹配。)
如果效果未收到已发送的操作,则最有可能的解释是,您store
发送的StandardSigninAction
与store
的效果不同SessionEffects
使用 - 也就是说,你有DI问题。
如果是这种情况,您应该查看与您说的其他StandardSigninAction
有何不同之处。 (至少你有一些工作,这是一个开始试验的好地方。)他们是从一个不同的模块发送的吗?分配SessionEffects
功能模块的模块是什么?
如果您破解其中一个工作StandardSigninAction
以将其分派的操作替换为11110001000010100000011000000110000001100000010100001000111100
,会发生什么?效果会运行吗?
请注意,本答案末尾的问题不是我想回答的问题;他们是你应该问自己和调查的问题。
答案 1 :(得分:7)
您的商店的流可能因为未处理的错误而停止,或者 - 可能更容易混淆 - 使用.catch
看起来“处理”的错误实际上会杀死流而不重新发出新的Observable以保持正常运行。< / p>
例如,这将终止流:
this.actions$
.ofType('FETCH')
.map(a => a.payload)
.switchMap(query => this.apiService.fetch$(query)
.map(result => ({ type: 'SUCCESS', payload: result }))
.catch(err => console.log(`oops: ${err}`))) // <- breaks stream!
但这会让事情保持活力:
this.actions$
.ofType('FETCH')
.map(a => a.payload)
.switchMap(query => this.apiService.fetch$(query)
.map(result => ({ type: 'SUCCESS', payload: result }))
.catch(e => Observable.of({ type: 'FAIL', payload: e}))) // re-emit
对于任何rxjs Observable btw都是如此,在向多个观察者广播时尤为重要(如ngrx商店内部使用内部Subject
)。
答案 2 :(得分:1)
如果您使用的是版本8,请确保用createEffect
包装每个动作。
示例:
Create$ = createEffect(() => this.actions$.pipe(...))
答案 3 :(得分:0)
我正在使用更高版本的ngrx(7.4.0),因此cartan的建议是:
.do((action) => console.log(`Received ${action.type}`))
应该是...
... = this.actions.pipe(
tap((action) => console.log(`Received ${action.type}`)),
...
最后,我发现我错过了将新效果导出添加到模块的过程,例如:
EffectsModule.forRoot([AuthEffects, ViewEffects]), // was missing the ', ViewEffects'
答案 4 :(得分:0)
另一个可能的原因是,如果您使用ng generate来创建要在其中导入效果的模块,请确保将其导入到应用模块中,因为以下命令“ ng generate module myModule”不会将其添加到应用模块中。