Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

http-interceptor to wait for subscribe to finish getting data

Tags:

angular

I am having an HTTP Interceptor. The backend API expects custom headers whose values are stored in indexdb during app initialization and other operations. Hence, I need to get the values and pass it with every request. But so far, failing to do so as the interceptor does not wait for the subscription to finish executing and sends requests without the custom headers.

The intercetpor does get the currently saved or default headers but it is too late as the request goes thru without the headers.

indexdb.service.ts:

@Injectable()
export class IndexDBService {
  /*
    Handles configuration of the app:
        reading current configuration
        saving configuration
    */

  private pouch: any;

  constructor() {
    this.pouch = new PouchDB("config", {
      auto_compaction: true
    });
  }

  currentConfig(): Observable<any> {
    /*
      Return the current configuration saved in the database
    */
    let vm = this;
    return new Observable(observer => {
      vm.pouch.get("info", function(err, doc) {
        if (err) {
          console.log("config read error ", err);
          // create a default one
            configOptions={'header1': '1','header2':2}
           observer.next(configOptions);
        } else {

          observer.next(doc);
        }
      });
    });
  }
}

interceptor.ts

import { Injectable } from "@angular/core";
import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest,
  HttpHeaders
} from "@angular/common/http";
import { Observable } from "rxjs";
import { IndexDBService } from "../services/indexdb.service";

@Injectable()
export class InterceptAPICalls implements HttpInterceptor {
  constructor(private indexdbService: IndexDBService) {}

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {

    this.indexdbService.currentConfig().subscribe(configData => {
      console.log(configData); // ==> does work great. I am getting data right
      req = req.clone({
        headers: new HttpHeaders({

          "X-Header1": configData["header1"],
          "X-Header2": configData["header2"]
        })

      });
      return next.handle(req); // want this one to return always
    });
    // below is cos the app won't compile and it returns immediately
    return next.handle(req);
  }
}
like image 467
Nie Selam Avatar asked Oct 21 '25 04:10

Nie Selam


2 Answers

The intercept function just needs to return an observable. So you start be making a request to the currentConfig() and then switch to the next interceptor when the config is emitted.

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return this.indexdbService
        .currentConfig()
        .pipe(
            first(),
            mergeMap(configData => {
                req = req.clone({
                    headers: new HttpHeaders({
                        'X-Header1': configData['header1'],
                        'X-Header2': configData['header2']
                    })
                });
                return next.handle(req);
            })
        );
}
like image 200
Reactgular Avatar answered Oct 22 '25 22:10

Reactgular


you can use mergeMap to create async interceptor

intercept(
    req: HttpRequest<any>,
    next: HttpHandler
    ): Observable<HttpEvent<any>> {

    return this.indexdbService.currentConfig().pipe(mergeMap(configData => {
      console.log(configData); // ==> does work great. I am getting data right
      req = req.clone({
         headers: new HttpHeaders({
          "X-Header1": configData["header1"],
          "X-Header2": configData["header2"]
         });
       });
       return next.handle(req);
      })
     );
}
like image 22
Fateh Mohamed Avatar answered Oct 22 '25 23:10

Fateh Mohamed



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!