http-interceptor等待订阅完成获取数据

时间:2019-05-25 14:31:13

标签: angular

我有一个HTTP拦截器。后端API需要自定义标头,其值在应用程序初始化和其他操作期间存储在indexdb中。因此,我需要获取值并将其随每个请求传递。但是到目前为止,由于拦截器没有等待订阅完成执行并发送没有自定义标头的请求,因此未能这样做。

intercetpor确实获得了当前保存的或默认的标头,但为时已晚,因为没有标头的请求通过了。

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);
  }
}

2 个答案:

答案 0 :(得分:3)

您可以使用 mergeMap 创建异步拦截器

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);
      })
     );
}

答案 1 :(得分:1)

拦截函数只需要返回一个可观察值。因此,您开始向currentConfig()发出请求,然后在发出配置时切换到下一个拦截器。

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);
            })
        );
}