我创建了一个DataModule,其中包含用于访问我的后端API的所有http服务类。在http错误,例如401或403我希望能够重定向到/ login或尝试刷新令牌等。
我想在离子应用程序中重用这个DataModule,所以不要与路由器模块或其他任何东西耦合。
目前,我在AppModule中导入DataModule时通过forRoot方法传递一些原始值:
DataModule.forRoot({
url: environment.apiEndpoint,
token() {
return localStorage.getItem('auth_token')
},
onError(errors: any) {
console.log(this);
}
});
我需要onError回调才能调用router.navigate(' / login')或类似的,但因为这是一个简单的配置对象,所以我不认为可以注入路由器。
我正在寻找一种传递内容的方法,并且已经回顾了其他几个流行的ng项目,例如ngx-translate,angularitics2和ngx-restangular,这些项目都通过提供程序,这些提供程序似乎随后由组件提供。这是通过传入AuthException服务或实现DataModule包中保存的接口的类似方法来实现我所追求的目标吗?
更新
我最终从我提到的项目中获取了这个想法,这对我的DataModule来说有一个默认的错误处理服务,基本上什么也没做。然后,我在forRoot中注入一个特定于应用程序的更好的错误处理类,然后在提供程序中使用它:
static forRoot(config: any): ModuleWithProviders {
return {
ngModule: DataModule,
providers: [
config.authExceptionService || AuthExceptionService,
{ provide: CONFIG, useValue: config },
{
provide: ApiService,
useFactory: ApiServiceFactory,
deps: [Http, config.authExceptionService || AuthExceptionService, CONFIG]
},
]
}
}
我的ApiServiceFactory供参考:
export function ApiServiceFactory(http: Http, authException: AuthExceptionService, config: any) {
return new ApiService(http, authException, {
url: config.url,
token: config.token
});
}
我还必须使用InjectionToken才能将我的配置对象作为工厂的依赖项提供:
export const CONFIG = new InjectionToken<any>('CONFIG');
从我的主应用程序中,我执行以下操作:
DataModule.forRoot({
authExceptionService: AppAuthExceptionService,
url: environment.apiEndpoint,
token() {
return localStorage.getItem('auth_token')
}
});
如果这种方法存在任何潜在问题,很高兴听到任何人的意见。我希望我能够在离子应用程序中使用此模块,如下所示:
DataModule.forRoot({
authExceptionService: MobileAppAuthExceptionService,
url: environment.apiEndpoint,
token() {
return storage.getItem('auth_token') // ionic uses different storage
}
})
答案 0 :(得分:0)
您可以展开Http
并应用filter
export class MyHttp extends Http {
//...
constructor(){super()}
get(){
super.get()
.filter(x => {
// do your logic here
if(x.status === 403){
router.navigate( errorPage )
return false;
}
})
}
}
或者使用map并抛出错误
if (response.status === 403) {
throw Observable.throw(response);
}
并且有一个执行重定向的catch函数(imo是更好的方法)。
答案 1 :(得分:0)
一种可能的解决方案是在每个项目中扩展DataModule并分别覆盖onError和构造函数方法。
export class MyDataModule extends DataModule {
static ForRoot(...){
...
}
constructor(...args, private router: Router){
super(...args)
}
onError() {
this.router.navigate(errorPage);
}
}
然后在您的离子应用程序中,您可以通过其他方式处理错误。