Fetch API:请求完成后 'await res.json()' 会失败吗?

Fetch API: Can 'await res.json()' fail after a completed request?

获取 API 请求只有在出现网络或服务器错误时才会失败。因此,例如,如果我执行以下代码,假设它没有错误地通过 try 块,我将有一个有效的填充 res.

try {
    const res = await fetch('/createurl', { 
        method: 'POST',
        body: 'testData',
        headers: {
            'Content-Type': 'application/json'
        }
    })

    if (res.ok) {
        alert('Resource created!')
    } else {
        alert('Error creating resource!')
    }

    flashResponseToUser(res)
} catch(e) {
    alert('A server or network error occurred during the request!')
}

我正在处理 res 以使用 flashResponseToUser(res) 函数向用户显示必要的 errorsuccess 消息。由于 res.json() return 是一个 PromiseflashResponseToUser 必须是一个异步函数。

const flashResponseToUser = async(res) => {
    const jsonRes = await res.json() // Get data from response
    console.log(jsonRes)
}

我想知道:

  1. 为什么 res.json() return 一个 Promise 因为此时客户端已经收到响应?
  2. res.json() 编辑的 Promise return 在什么情况下会失败?
  3. flashResponseToUser(res) 中的代码是否也需要包含在 try-catch 块中,因为我正在使用 res.json()

Why does res.json() return a Promise since at this point the response has already been received by the client?

fetch returns 回复 object。这表示已收到响应的 headers,但并不一定意味着已收到整个响应 - 例如,想象一下,当您加载一个巨大的页面时.这与 完全 不同,但您会收到 headers 并且浏览器将开始加载响应,即使还有更多内容需要下载。响应 object 提供 headers 和处理 still-incoming 数据的方法。

Under what conditions would the Promise returned by res.json() fail?

如果响应的格式不正确 JSON,它可能会失败。例如,如果响应的纯文本是 Internal Server Error,则不是 JSON。这是一个例子:

(async () => {
  const response = await fetch('data:,Internal%20Server%20Error');
  console.log('got response');
  try {
    await response.json();
  } catch(e) {
    console.log('error:', e.message);
  }
})();

Does the code within flashResponseToUser(res) also need to be wrapped within a try-catch block since I am using res.json()?

如果您想绝对安全,可以。但是,在大多数情况下,最简单的方法是在 一个地方 捕获,在那里您可以处理错误。您可以在消费者中只处理一次错误,而不是在流程的每一步都处理可能的错误,例如:

const getInfo = async () => {
  const res = await fetch('/createurl', { 
    method: 'POST',
    body: 'testData',
    headers: {
      'Content-Type': 'application/json'
    }
  })

  if (!res.ok) {
    throw new Error(res.status);
  }
  return res.json();
};
getInfo()
  .then(flashResponseToUser)
  .catch(() => {
    alert('A server or network error occurred during the request!')
  })

(假设 flashResponseToUser 永远不会抛出,如果提供了预期的 object。如果 flashResponseToUser 无论如何都可能抛出,您可以将 .catch 分离出来区分网络错误和其他运行时错误)