首页 > 解决方案 > Angular:带有空 200/201 响应的 HttpClient 错误(始终调用 JSON.parse(""))

问题描述

在使用 AngularHttpClient post时,似乎默认将响应视为 JSON 字符串。当响应正文为空时,即使为 201 响应也会导致错误,因为空字符串""失败JSON.parse()

解决方案是指定responseType: "text"为附加选项,以便不将空正文视为错误。

但是,当请求失败时,API 端点会以 JSON 格式返回错误描述(即成功时为空,错误时为 JSON)。

您如何构造,HttpClient post以便在错误消息对象失败并且成功不算作错误时返回错误消息对象?

例如:

.subscribe(() => {
    // do something for success, no return object as the body is empty
  , error => {
    // do something with the returned error object
    // right now success is still counted as an error due to the issue above
  }
);

标签: jsonangular

解决方案


返回响应代码200201具有响应正文并Content-Type指定为application/json的服务器配置错误,因为空字符串不是有效的 JSON。

正如 OP 所指出的,指定responseType: "text"修复了错误,因为空正文没有被解析为 JSON。

一种解决方法是继续responseType: "text"检查响应正文是否为空。如果响应正文不为空,则调用JSON.parse(response).

例子

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';


type HttpOptions = {
  headers?: HttpHeaders | { [header: string]: string | string[]; };
  observe?: "body"; params?: HttpParams | { [param: string]: string | string[]; };
  reportProgress?: boolean; responseType?: "json" /* or "text" as "json" */;
  withCredentials?: boolean;
}

let get_http_options_text = (): HttpOptions => {
  return {
    headers: {'Content-Type': 'text/plain'},
    observe: "body",
    responseType: "text" as "json",  // @see https://github.com/angular/angular/issues/18586
    withCredentials: true
  }
}


@Injectable()
export class MyHttpService {

  constructor(private http: HttpClient) {}

  public post_body_as_string(url: string, body: any, http_params: HttpParams = null):
    Observable<any> {

    let options = get_http_options_text();
    if (http_params != null) {
      options['params'] = http_params;
    }

    return this.http.post<string>(url, body, options).pipe(
      map(response => {
        if (response !== '') {
          return JSON.parse(response);
        } else {
          return {}
        }
      })
    );
  }
}

推荐阅读