HttpClient无法解析空响应

时间:2017-11-09 16:43:11

标签: angular observable interceptor

我有一个在标头中添加令牌的拦截器。但是,如果我在POST请求后使用它,则不会触发订阅中的Observer。

拦截器:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.authService = this.inj.get(AuthService);
if (!this.authService.isLoggedIn()) {
  return next.handle(req);
}

const changedReq = req.clone({headers: req.headers.set('Authorization', `Bearer ${this.authService.getToken()}`)});
return next.handle(changedReq);
}

服务:

saveBeer(beerForm: BeerForm): Observable<Response> {
let body = JSON.stringify(beerForm);
let headers = new HttpHeaders({
  'Content-Type': 'application/json'
});

return this.http.post(this.apiUrl, body, {headers: headers});
}

组件:

onSubmitCreateBeer(): void {
this.beerService.saveBeer(this.beerForm)
  .takeUntil(this.ngUnsubscribe)
  .subscribe(
    (response: Response) => {
      // On response
      this.router.navigate(['/beers']);
    }, error => {
      // On error
    }, () => {
      // On complete
    });
}

我的问题是,响应永远不会被触发,所以我的导航步骤不起作用。如果我禁用拦截器一切正常。

有什么想法吗?

2 个答案:

答案 0 :(得分:14)

我得到了它的工作。问题是我的观察者在回应中期待json。然而,在我得到200 OK之后,响应中没有任何内容。这是一个错误,因此调用了错误函数。

解决方案1是设置responseType:text。

saveBeer(beerForm: BeerForm): Observable<any> {
let body = JSON.stringify(beerForm);
let headers = new HttpHeaders({
  'Content-Type': 'application/json'
});

return this.http.post(this.apiUrl, body, {headers: headers, responseType: 'text'});
}

解决方案2是从后端返回204。

现在两者都很好。有关于此的错误报告:

https://github.com/angular/angular/issues/18680

答案 1 :(得分:1)

我的解决方法是一个HttpInterceptor,它在状态代码为200时捕获错误并返回一个带有空体的HttpResponse(就像HttpClient的204 Not Content响应一样):

@Injectable()
export class EmptyResponseBodyErrorInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
  .catch((err: HttpErrorResponse) => {
    if (err.status == 200) {
      const res = new HttpResponse({
        body: null,
        headers: err.headers,
        status: err.status,
        statusText: err.statusText,
        url: err.url
      });
      return Observable.of(res);
    } else {
      return Observable.throw(err);
    }
  });
 }
}