【问题标题】:Using Angular 2+ forRoot pattern to pass callbacks into modules使用 Angular 2+ forRoot 模式将回调传递给模块
【发布时间】:2017-06-12 13:54:42
【问题描述】:

我创建了一个名为 DataModule 的 Angular 模块,其中包含用于通过令牌保护的 HTTP API 访问我的后端的服务。关于401 Unauthorized403 Forbidden 等HTTP 访问控制错误,我希望能够重定向到/login 或尝试刷新令牌等。

我想在 Ionic 应用程序中重复使用这个 DataModule,所以我不希望与标准 @angular/router 有任何耦合 RouterModule 或其他任何东西。

目前,在我的AppModule 中导入DataModule 时,我通过forRoot 方法传入了一些原始值:

DataModule.forRoot({
  url: environment.apiEndpoint,
  token() {
     return localStorage.getItem('auth_token')
  },
  onError(errors: any) {
     console.log(this);
  }
});

我需要onError 回调才能调用router.navigate('/login') 或类似的,但由于这是一个简单的配置对象,我不认为router 可以在此阶段注入。

我正在寻找一种方法来传递这样的东西,并且我已经审查了其他几个流行的 ng 项目,例如 ngx-translateangularitics2ngx-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')
      }
    });

如果这种方法存在任何潜在问题,很高兴听到任何人的意见。我希望我应该能够在 Ionic 应用程序中使用这个模块,如下所示:

DataModule.forRoot({
      authExceptionService: MobileAppAuthExceptionService,
      url: environment.apiEndpoint,
      token() {
        return storage.getItem('auth_token') // ionic uses different storage
      }
    })

【问题讨论】:

    标签: angular angular2-modules angular2-providers


    【解决方案1】:

    您可以扩展 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 是更好的方法)。

    【讨论】:

      【解决方案2】:

      一种可能的解决方案是在每个项目中扩展您的 DataModule 并分别覆盖 onError 和构造函数方法。

      export class MyDataModule extends DataModule {
      
        static ForRoot(...){
          ...
        }
      
        constructor(...args, private router: Router){
          super(...args)
        }
      
        onError() {
          this.router.navigate(errorPage);
        }
      }
      

      然后在您的离子应用程序中,您可以通过其他方式处理错误。

      【讨论】:

        猜你喜欢
        • 2019-12-10
        • 2020-10-06
        • 2020-02-14
        • 2016-11-30
        • 2019-04-10
        • 2018-09-18
        • 1970-01-01
        • 1970-01-01
        • 2018-05-22
        相关资源
        最近更新 更多