在 fetch() Promise 中,如何在状态为 4xx 或 5xx 时捕获服务器错误消息?

Within a fetch() Promise, how to .catch server errors messages when status is 4xx or 5xx?

在本地 运行 Node.js 脚本中,这在状态为 200 时有效:

// module file
import fetch from "node-fetch";
export const getJSON = () => {
  const url = 'https://api.somesite.com/api/v0/etc';
  const options = {method: 'GET', headers: {Accept: 'application/json'}};
  const request = fetch(url, options)
    .then(response => response.json())
    .catch(err => console.log("somesite:", err));
  return Promise.resolve(request);
};

// execution file
import { getJSON } from './libs/api_requests.mjs';
console.log("func call", await getJSON());

但是当响应状态为 4xx 或 5xx 时,fetch 也可以在不触发 .catch 逻辑的情况下工作(参见示例 )。

执行没有中断,当函数被调用时我实际上收到一条错误消息,就好像那是正确的、正常的结果——作为 response.json().

的输出

此消息是简单的英语,类似于“错误:'路径不正确。请检查 https://www.somesite.com/api/'"

我想 preserve/display 这条错误消息,只是我想在模块文件的函数 getJSON 中捕获它,而不必在目标位置围绕它包装一些逻辑,可能会在调用函数的任何地方多次重复相同的代码,而不是只在源头处理一次问题。

所以我修改了 .then 子句,这样也有效:

.then(response => { if (response.ok) { // .ok should be status 200 only, I suppose
        return response.json();
      } else { throw new Error(response.status) }

现在这会按预期触发 .catch 子句,显示“错误:404 [etc]”。除了我想抛出的是原始错误消息“不正确的路径 [etc]” 和 that 我做不到。我试过了

.then(response => { if (response.ok) {
      return response.json();
    } else { throw new Error(response.json()) } // somesite: Error: [object Promise]

.then(response => { if (response.ok) {
      return response.json()
    } else { throw new Error(Promise.resolve(response.json())) } // somesite: Error: [object Promise]

.then(response => { if (response.ok) {
      return response.json()
    } else { throw new Error(return response.json()) } // SyntaxError: Unexpected token 'return'

.then(response => { if (response.ok) {
        return response.json();
      } else { throw new Error(Promise.resolve(request)) } // somesite: Error: [object Promise]

我想我需要解决 response.json() promise 就好像一切正​​常一样,但该怎么做?

我还用 console.dir(request, { depth: null }) 查看了 request 对象,看看是否可以从那里提取错误消息,但我找不到它,而且该对象仍然包含许多未展开的例如 [Function: onerror][Function: onclose] 等元素。

当状态代码为 400500 时,尝试 response.text() 而不是 response.json()。 根据我的经验,错误消息通常由 text 回调返回。


参见 this answer 类似问题。


编辑:

添加了以下代码,由 OP 建议。

.then((response) => {
  if (response.ok) {
    return response.json();
  }
  else {
     return response.text()
       .then((text) => {
         throw(text);

         // if the error is an object and you just want to display some elements:
         throw(JSON.parse(text));
       });
  }
})
.catch((err) => {
  // in case you want to log the error
  console.log("somesite: ", err));

  return new Error("somesite: " + err);
});