获取 API:在请求完成后“await res.json()”能否失败?

phi*_*her 10 javascript promise fetch-api

fetch 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!')
}
Run Code Online (Sandbox Code Playgroud)

我正在处理res向用户显示使用该功能的必要信息errorsuccess消息flashResponseToUser(res)。由于res.json()返回 a PromiseflashResponseToUser必须是一个异步函数。

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

我想知道:

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

Cer*_*nce 15

为什么 res.json() 会返回一个 Promise ,因为此时客户端已经收到了响应?

fetch返回一个响应对象。这表示已收到响应的标头,但并不一定意味着已收到整个响应 - 例如,当您加载一个大页面时。这并不完全相同,但您会收到标头,浏览器将开始加载响应,即使还有更多内容要下载。Response 对象提供标头和处理仍然传入数据的方法。

res.json() 返回的 Promise 在什么情况下会失败?

如果响应不是正确的 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);
  }
})();
Run Code Online (Sandbox Code Playgroud)

因为我使用的是 res.json(),所以 flashResponseToUser(res) 中的代码是否也需要包含在 try-catch 块中?

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

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!')
  })
Run Code Online (Sandbox Code Playgroud)

(假设flashResponseToUser永远不会抛出,如果提供了预期的对象。如果flashResponseToUser可能会抛出,您可以将.catches分开以将网络错误与其他运行时错误区分开来)