Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
369 views
in Technique[技术] by (71.8m points)

angular - how to provide interceptor optionally

I have two interceptors -- MainInterceptor and OptionalInterceptor.

export const httpInterceptorProviders = [
    { provide: HTTP_INTERCEPTORS, useClass: MainInterceptor, multi: true }, 
    { provide: HTTP_INTERCEPTORS, useClass: OptionalInterceptor, multi: true }
];

and I provide them in app.module:

providers: [
    ...
    httpInterceptorProviders
]

The logic inside OptionalInterceptor should be executed only in specific conditions (depending on the value of a cookie). I have a service ConfigService that reads the cookie and knows the condition. Right now I inject this service in OptionalInterceptor and execute the logic or not depending on service state.

However the cookie is available (or not) at load time, hence it feels it would be cleaner not to load the OptionalInterceptor at all.

I could create NoopInterceptor and do something like:

export const httpInterceptorProviders = [
    { provide: HTTP_INTERCEPTORS, useClass: MainInterceptor, multi: true }, 
    { provide: HTTP_INTERCEPTORS, useFactory: (srv: ConfigService) => srv.optional ? OptionalInterceptor: NoopInterceptor, multi: true, deps: [ConfigService] }
];

but it does not feel any better. Finally I could define httpInterceptorProviders as a factory:

export const httpInterceptorProviders = (srv: ConfigService) => {...}

in this case I do not see how can I inject the service in module:

httpInterceptorProviders(injectedService)

or

{provide: ???, useFactory: httpInterceptorProviders, deps:[ConfigService]}

Well there is also an approach from this answer. It provides different HttpClient instances injected with different interceptors, but for a simple case this solution looks worse than the problem. It strictly gets the job done, but with even less elegance than doing ifs to skip the logic or creating a NoopInterceptor.

(edit) Just to clarify: why I prefer forcing to load interceptors conditionally instead of applying the condition in the interceptor code? I regard applying condition during the loading of the interceptor to be more clear and maintainable. In order to avoid questions like "why our interceptor is not working, is it broken?" and going to the interceptor code for answer.

question from:https://stackoverflow.com/questions/66068721/how-to-provide-interceptor-optionally

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I ended up by coding two acceptable versions. One works by directly retrieving the cookie (no point on injecting the service for this trivial task):

export const mainHttpInterceptorProviders = [...];
export const httpInterceptorProvidersWithOptional = [
    ...mainHttpInterceptorProviders,
    { provide: HTTP_INTERCEPTORS, useClass: OptionalInterceptor, multi: true }
];
export const getHttpInterceptorProviders = () => {
    return getCookie(cookieOptional) ? httpInterceptorProvidersWithOptional : mainHttpInterceptorProviders;
}

and in module:

providers: [
    ...
    getHttpInterceptorProviders()
]

The other option is by using NoopInterceptor and useFactory. NoopInterceptor explicitly says that interceptor is just a placeholder and does no work. I already mentioned this option in my question and after evaluating the options decided to go with it:

export class NoopInterceptor implements HttpInterceptor {
 intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
   return next.handle(req);
 }
}
export const httpInterceptorProviders = [ 
    ...mainHttpInterceptorProviders,
    { 
      provide: HTTP_INTERCEPTORS, 
      useFactory: (srv: ConfigService) => srv.optional ? new OptionalInterceptor(): new NoopInterceptor(), 
      multi: true, deps: [ConfigService]
    }
];

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...