Fetch API:请求完成后“await res.json()”会失败吗?
Posted
技术标签:
【中文标题】Fetch API:请求完成后“await res.json()”会失败吗?【英文标题】:Fetch API: Can 'await res.json()' fail after a completed request? 【发布时间】:2020-04-30 21:31:07 【问题描述】:只有在出现网络或服务器错误时,提取 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)
函数向用户显示必要的error
或success
消息。由于res.json()
返回一个Promise
,flashResponseToUser
必须是一个异步函数。
const flashResponseToUser = async(res) =>
const jsonRes = await res.json() // Get data from response
console.log(jsonRes)
我想知道:
-
为什么
res.json()
返回Promise
,因为此时客户端已经收到响应?
在什么情况下res.json()
返回的Promise
会失败?
由于我使用的是res.json()
,flashResponseToUser(res)
中的代码是否也需要包装在 try-catch
块中?
【问题讨论】:
developer.mozilla.org/en-US/docs/Web/API/Body 这将能够帮助您解决这些问题。 @Siege21x 我确实读过,但它仍然没有解释为什么 res.json() 返回一个 Promise 而不是直接返回数据。也没有告诉我们 res.json() 在什么情况下失败。 answer 第一个问题。 answer 第二个问题。 【参考方案1】:为什么 res.json() 会返回一个 Promise,因为此时客户端已经收到了响应?
fetch
返回一个响应对象。这表明响应的 headers 已收到,但并不一定意味着整个响应已收到 - 例如,当您加载一个巨大的页面时。这不是完全相同的东西,但是您会收到标头并且浏览器将开始加载响应,即使还有更多要下载的内容。 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);
)();
由于我使用的是 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!')
)
(假设flashResponseToUser
永远不会抛出,如果提供了预期的对象。如果flashResponseToUser
无论如何都可能抛出,您可以分离出.catch
es 以区分网络错误和其他运行时错误)
【讨论】:
谢谢!很好的解释。我会尽快将此标记为答案! JSON 格式错误发生的频率比人们想象的要多。有时你的框架会返回一个错误页面,它是 html 而不是 json。有时您的反向代理(nginx 或 apache 前端)会返回一个错误页面,该页面是 HTML 而不是 json。有时您的办公室或 ISP 缓存服务器会返回一个错误页面,该页面是 HTML 而不是 json。您不一定能控制所有条件 哦,别忘了公共Wifi有时会劫持你的请求并返回一个HTML而不是json的登录页面以上是关于Fetch API:请求完成后“await res.json()”会失败吗?的主要内容,如果未能解决你的问题,请参考以下文章