ngf*_*ixl 9 typescript ngrx angular angular8
在使用NgRX 8时,我和我的同事在实现效果时经常会遇到奇怪的错误消息。
类型'Observable <未知>'不可分配给类型'Observable <动作> | ((... args:any [])=> Observable <Action>)'
它与类型问题有关。消息如此具体,真是令人讨厌,它标志着完整的效果。这经常出现,而且确实很难解决。
我们想知道是否可以做些事情以便快速发现问题,或者我们是否能够以某种方式破坏消息的结构。我不是在这里寻找特定的解决方案,而是在寻找一种“如何快速确定问题出在哪里”的方法。
谢谢和欢呼!
这是我们到目前为止所做的,也是来自评论和答案的想法。
switchMap参数的错误解构可能是错误的我们仍然希望有一个技巧来分解错误消息。
And*_*len 11
更新-快速版本 -注释掉createEffect(() =>,修复IDE(VSCode)标记的错误,然后createEffect(() =>重新添加。
较早的答案 - @Effect不需要使用,也不是必需的。
我发现调试的最简单方法是使用@Effect装饰器以版本7的方式编写代码,并使用完成重写createEffect。
因此要调试:
navigateToDashboard$ = createEffect(() =>
this.actions$.pipe(
ofType(teamActions.CREATE_SUPERVISOR_GROUP_SUCCESS),
map((action: teamActions.CreateSupervisorGroupSuccess) => action.payload),
map((team: Team) => team.TeamID),
SwitchMap(id => new routerActions.Go({ path: ['/team', id, 'populate'] }))
)
)
Run Code Online (Sandbox Code Playgroud)
这将无用的错误写为(添加装饰器,删除createEffect(() =>,删除最后的括号),
@Effect()
navigateToDashboard$ = this.actions$.pipe(
ofType(teamActions.CREATE_SUPERVISOR_GROUP_SUCCESS),
map((action: teamActions.CreateSupervisorGroupSuccess) => action.payload),
map((team: Team) => team.TeamID),
SwitchMap(id => new routerActions.Go({ path: ['/team', id, 'populate'] }))
)
Run Code Online (Sandbox Code Playgroud)
现在我们得到了错误
Cannot find name 'SwitchMap'
Run Code Online (Sandbox Code Playgroud)
其次是
Type 'Go' is not assignable to type 'ObservableInput<any>'
Run Code Online (Sandbox Code Playgroud)
解决这个问题
@Effect()
navigateToDashboard$ = this.actions$.pipe(
ofType(teamActions.CREATE_SUPERVISOR_GROUP_SUCCESS),
map((action: teamActions.CreateSupervisorGroupSuccess) => action.payload),
map((team: Team) => team.TeamID),
switchMap(id => of(new routerActions.Go({ path: ['/team', id, 'populate'] })))
)
Run Code Online (Sandbox Code Playgroud)
现在用NgRx 8项重写。不漂亮,但可以。
小智 9
我遇到了完全相同的问题,就我而言,这是因为错误放置的大括号和缺少导入。
这是我为调试和解决它所做的。
将内部可管道功能拆分为单独的功能。这对我来说是最重要的一步,因为复杂的语法和来自 vscode 的自动完成大括号,有时大括号存在于错误的位置并且不容易找到。这也解决了几乎所有其他问题(缺少导入、不正确的返回类型等),因为要调试的代码要小得多,而且 vscode 会从子函数中突出显示这个单独的错误。
这是我以前的
performLogin$ = createEffect(() =>
this.actions$.pipe(
ofType(performLogin),
mergeMap(() => this.loginService.performLogin().pipe(
map(() => loginSuccess())
)))
);
Run Code Online (Sandbox Code Playgroud)
把这个改成下面
performLogin$ = createEffect(() =>
this.actions$.pipe(
ofType(performLogin),
mergeMap(() => this.performLogin()),
catchError((error ) => { console.log("HELLO"); return EMPTY})
)
);
performLogin() {
return this.loginService.performLogin()
.pipe(map(() => loginSuccess()));
}
Run Code Online (Sandbox Code Playgroud)
我从这种方法中得到的另一个好处是内管上的 catchError 块不会被触发(根据效果示例它应该可以工作)。因此必须将其包含在外部管道块中。这里错误被捕获并按预期工作。但仍在弄清楚为什么它不起作用。
总结一下,登录服务做了以下事情(抛出错误或者返回Observable为true)
//login.service.ts
performLogin() : Observable<boolean> {
throw "Something went wrong";
//return of(true);
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助。
在处理此问题并使用官方 ngrx 8 示例的情况下。
loadMovies$ = createEffect(() => this.actions$.pipe(
ofType('[Movies Page] Load Movies'),
mergeMap(() => this.moviesService.getAll()
.pipe(
map(movies => ({ type: '[Movies API] Movies Loaded Success', payload: movies })),
catchError(() => EMPTY)
))
)
);
Run Code Online (Sandbox Code Playgroud)
简单快速的解决方案可以放置“任何”类型。
loadMovies$: any = createEffect((): any => this.actions$.pipe(
ofType('[Movies Page] Load Movies'),
mergeMap(() => this.moviesService.getAll()
.pipe(
map(movies => ({ type: '[Movies API] Movies Loaded Success', payload: movies })),
catchError(() => EMPTY)
))
)
);
Run Code Online (Sandbox Code Playgroud)
不要忘记 rxjs 操作符的导入,observables。
在处理动作负载 - 道具的情况下,定义动作类型。
ofType<MySuperActions>
Run Code Online (Sandbox Code Playgroud)
或者
ofType<ReturnType<typeof myAction>>
Run Code Online (Sandbox Code Playgroud)