Angular http侦听器等待subscribe完成数据获取

Angular http侦听器等待subscribe完成数据获取,angular,Angular,我有一个HTTP拦截器。后端API需要自定义头,其值在应用程序初始化和其他操作期间存储在indexdb中。因此,我需要获取值并在每个请求中传递它。但到目前为止,由于拦截器没有等待订阅完成执行并发送不带自定义头的请求,因此未能执行此操作 intercetpor确实获取当前保存的或默认的标头,但由于请求没有标头而通过,因此为时已晚 indexdb.service.ts: @Injectable() export class IndexDBService { /* Handles conf

我有一个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);
        }
      });
    });
  }
}
@Injectable()
导出类IndexDBService{
/*
处理应用程序的配置:
读取当前配置
保存配置
*/
私人邮袋:任何;
构造函数(){
this.pocks=新的PockDB(“配置”{
自动压缩:真
});
}
currentConfig():可观察{
/*
返回保存在数据库中的当前配置
*/
让vm=这个;
返回新的可观察对象(观察者=>{
vm.pocket.get(“信息”,函数(err,doc){
如果(错误){
log(“配置读取错误”,err);
//创建一个默认值
configOptions={'header1':'1','header2':2}
下一步(配置选项);
}否则{
下一个观察员(doc);
}
});
});
}
}
拦截器

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);
  }
}
从“@angular/core”导入{Injectable};
进口{
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpHeader
}来自“@angular/common/http”;
从“rxjs”导入{observeable};
从“./services/indexdb.service”导入{IndexDBService};
@可注射()
导出类拦截器实现HttpInterceptor{
构造函数(私有indexdbService:indexdbService){}
拦截(
请求:HttpRequest,
下一步:HttpHandler
):可见{
此.indexdbService.currentConfig().subscribe(configData=>{
console.log(configData);//=>工作得很好。我得到的数据是正确的
req=req.clone({
标题:新的HttpHeaders({
“X-Header1”:配置数据[“Header1”],
“X-Header2”:配置数据[“Header2”]
})
});
return next.handle(req);//希望这个始终返回
});
//下面是因为应用程序无法编译,它会立即返回
返回next.handle(req);
}
}

您可以使用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);
      })
     );
}
拦截(
请求:HttpRequest,
下一步:HttpHandler
):可见{
返回此.indexdbService.currentConfig().pipe(合并映射(configData=>{
console.log(configData);//=>工作得很好。我得到的数据是正确的
req=req.clone({
标题:新的HttpHeaders({
“X-Header1”:配置数据[“Header1”],
“X-Header2”:配置数据[“Header2”]
});
});
返回next.handle(req);
})
);
}

截取函数只需要返回一个可观察值。因此,您开始向
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);
            })
        );
}
intercept(req:HttpRequest,next:HttpHandler):可观察{
返回此。indexdbService
.currentConfig()
.烟斗(
第一个(),
合并映射(configData=>{
req=req.clone({
标题:新的HttpHeaders({
“X-Header1”:配置数据['Header1'],
“X-Header2”:配置数据['Header2']
})
});
返回next.handle(req);
})
);
}

我认为这是正确的答案。我本想说使用switchMap,但我意识到这是在一个拦截器中,它可以取消以前的拦截器。@cgTag为什么?虽然我以后必须检查Fateh的答案,但我无法让它工作,也无法在你的答案工作时编译出多个错误。接下来的返回给我类型为“{headers:HttpHeaders;return:Observable;}”的参数不能分配给类型为“{headers?:HttpHeaders;reportProgress?:boolean;params?等”的参数,而mergeMap(configData)给我类型为“(configData:any)=>void”的参数不能分配给类型为“(值:any,索引:number)的参数=>ObservableInput.类型'void'不可分配给类型'ObservableInput'@NieSelam源代码示例中存在语法错误。
req.clone
的代码块中有
return
语句。您应该使用
mergeMap
运算符的答案是正确的,但这个示例中有错误。很好格式化的代码和工作示例在stackoverflow上很重要。很抱歉,已经修复了