How use async service into angular httpClient interceptor

前端 未结 7 888
轻奢々
轻奢々 2020-12-09 18:53

Using Angular 4.3.1 and HttpClient, I need to modify the request and response by async service into the HttpInterceptor of httpClient,

Example for modifying the requ

相关标签:
7条回答
  • 2020-12-09 19:19

    The answers above seem to be fine. I had same requirements but faced issues due to update in different dependencies and operators. Took me some time but I found one working solution to this specific issue.

    If you are using Angular 7 and RxJs version 6+ with requirements for Async Interceptor request then you can use this code which works with latest version of NgRx store and related dependencies:

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    
        let combRef = combineLatest(this.store.select(App.getAppName));
    
        return combRef.pipe( take(1), switchMap((result) => {
    
            // Perform any updates in the request here
            return next.handle(request).pipe(
                map((event: HttpEvent<any>) => {
                    if (event instanceof HttpResponse) {
                        console.log('event--->>>', event);
                    }
                    return event;
                }),
                catchError((error: HttpErrorResponse) => {
                    let data = {};
                    data = {
                        reason: error && error.error.reason ? error.error.reason : '',
                        status: error.status
                    };
                    return throwError(error);
                }));
        }));
    
    0 讨论(0)
  • 2020-12-09 19:21

    Ok i am updating my answer, You cannot update the request or response in an asynchronous service, you have to update the request synchronously like this

    export class UseAsyncServiceInterceptor implements HttpInterceptor {
    
    constructor( private asyncService: AsyncService) { }
    
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
      // make apply logic function synchronous
      this.someService.applyLogic(req).subscribe((modifiedReq) => {
        const newReq = req.clone(modifiedReq);
        // do not return it here because its a callback function 
        });
      return next.handle(newReq); // return it here
     }
    }  
    
    0 讨论(0)
  • 2020-12-09 19:24

    I think that there is a issue about the reactive flow. The method intercept expects to return an Observable and you have to flatten your async result with the Observable returned by next.handle

    Try this

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
          return this.asyncService.applyLogic(req).mergeMap((modifiedReq)=> {
            const newReq = req.clone(modifiedReq);
            return next.handle(newReq);
        });
    }
    

    You could also use switchMap instead of mergeMap

    0 讨论(0)
  • 2020-12-09 19:27

    If you need to invoke an async function within interceptor then the following approach can be followed using the rxjs from operator.

    import { MyAuth} from './myauth'
    import { from } from 'rxjs'
    
    @Injectable()
    export class AuthInterceptor implements HttpInterceptor {
      constructor(private auth: MyAuth) {}
    
      intercept(req: HttpRequest<any>, next: HttpHandler) {
        // convert promise to observable using 'from' operator
        return from(this.handle(req, next))
      }
    
      async handle(req: HttpRequest<any>, next: HttpHandler) {
        // if your getAuthToken() function declared as "async getAuthToken() {}"
        await this.auth.getAuthToken()
    
        // if your getAuthToken() function declared to return an observable then you can use
        // await this.auth.getAuthToken().toPromise()
    
        const authReq = req.clone({
          setHeaders: {
            Authorization: authToken
          }
        })
    
        // Important: Note the .toPromise()
        return next.handle(authReq).toPromise()
      }
    }
    
    0 讨论(0)
  • 2020-12-09 19:27

    If I get your question right than you can intercept your request using deffer

       
    
    module.factory('myInterceptor', ['$q', 'someAsyncService', function($q, someAsyncService) {  
        var requestInterceptor = {
            request: function(config) {
                var deferred = $q.defer();
                someAsyncService.doAsyncOperation().then(function() {
                    // Asynchronous operation succeeded, modify config accordingly
                    ...
                    deferred.resolve(config);
                }, function() {
                    // Asynchronous operation failed, modify config accordingly
                    ...
                    deferred.resolve(config);
                });
                return deferred.promise;
            }
        };
    
        return requestInterceptor;
    }]);
    module.config(['$httpProvider', function($httpProvider) {  
        $httpProvider.interceptors.push('myInterceptor');
    }]);

    0 讨论(0)
  • 2020-12-09 19:33

    I am using an async method in my interceptor like this:

    @Injectable()
    export class AuthInterceptor implements HttpInterceptor {
    
        public constructor(private userService: UserService) {
        }
    
        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            return from(this.handleAccess(req, next));
        }
    
        private async handleAccess(req: HttpRequest<any>, next: HttpHandler):
            Promise<HttpEvent<any>> {
            const user: User = await this.userService.getUser();
            const changedReq = req.clone({
                headers: new HttpHeaders({
                    'Content-Type': 'application/json',
                    'X-API-KEY': user.apiKey,
                })
            });
            return next.handle(changedReq).toPromise();
        }
    }
    
    0 讨论(0)
提交回复
热议问题