Ngrx HTTP请求失败后重定向失效,页面空白问题求助
问题:Ngrx Effect错误重定向失效,页面空白仅显示
<app-root> 通过Ngrx Effect从HTTP服务加载数据,预期数据加载失败时重定向到指定URL,但重定向未生效,页面仅显示<app-root>标签,无任何渲染内容。
相关代码如下:
加载数据的Effect
loadConfig$ = createEffect(() => { return this.actions$.pipe( ofType(AppActionTypes.loadConfig), switchMap(() => { return this.configService.getConfig().pipe( map((config: any) => { console.log('loadConfig %o', config); return AppActionTypes.configLoaded({configuration: config}); }), catchError((err, caught) => { console.log('loadConfig catchErr %o', err); return of(AppActionTypes.errorAppInitializer(err)); }) ); }) ); });
错误重定向的Effect
errorAppInitializerRedirect$ = createEffect(() => { return this.actions$.pipe( ofType(AppActionTypes.errorAppInitializer), tap(() => { console.log('errorAppInitializerRedirect'); return this.router.navigateByUrl('/auth/errors'); }) ); } , {dispatch: false} );
解决方案
1. 修正错误Action的创建逻辑
代码中直接返回of(AppActionTypes.errorAppInitializer(err))是错误的——AppActionTypes是枚举类型,直接调用它无法生成有效的Action对象,导致后续Effect无法匹配该Action。
假设你的Action是用createAction定义的,正确写法如下:
// 先确保Action创建函数正确定义 export const errorAppInitializer = createAction( AppActionTypes.errorAppInitializer, props<{ error: any }>() ); // 在catchError中使用Action创建函数生成Action对象 catchError((err, caught) => { console.log('loadConfig catchErr %o', err); return of(errorAppInitializer({ error: err })); })
2. 替换tap为switchMap处理路由导航
router.navigateByUrl返回Promise,tap不会等待异步操作完成,尤其是在Angular初始化阶段,路由可能未完全就绪。改用switchMap结合from操作符处理Promise:
errorAppInitializerRedirect$ = createEffect(() => { return this.actions$.pipe( ofType(errorAppInitializer), // 使用Action创建函数匹配 switchMap(() => from(this.router.navigateByUrl('/auth/errors')).pipe( catchError(redirectErr => { console.error('重定向失败:', redirectErr); return EMPTY; }) ) ) ); }, { dispatch: false });
3. 确保APP_INITIALIZER流程不阻塞渲染
如果loadConfig$是在APP_INITIALIZER中触发的,必须保证初始化流程在错误发生时也能正常完成,否则Angular会卡住不渲染页面。修改APP_INITIALIZER配置:
// app.module.ts import { APP_INITIALIZER } from '@angular/core'; import { Store } from '@ngrx/store'; import { EMPTY } from 'rxjs'; import { catchError } from 'rxjs/operators'; providers: [ { provide: APP_INITIALIZER, useFactory: (store: Store) => () => store.dispatch(loadConfig()).pipe( catchError(() => EMPTY) // 确保流完成,不阻塞初始化 ), deps: [Store], multi: true } ]
4. 校验路由配置
确认/auth/errors对应的路由组件已正确注册,比如:
// app-routing.module.ts const routes: Routes = [ // 其他路由 { path: 'auth/errors', component: AuthErrorComponent } // 替换为你的错误组件 ];
内容的提问来源于stack exchange,提问作者Rosa
相关产品推荐
相关产品推荐

