JavaScript:有没有办法在响应不正常时检测响应是否包含json格式的错误消息
我正在编写一个简单的包装器fetch。
async function apiCall(
endpoint: string,
{
data,
headers: customHeaders,
...customConfig
}: { data?: Object; headers?: Object } = {}
) {
const config = {
method: data ? 'POST' : 'GET',
body: data ? JSON.stringify(data) : undefined,
headers: {
'content-type': data ? 'application/json' : undefined,
...customHeaders,
},
...customConfig,
}
return fetch(endpoint, config as any).then(async (response) => {
if (response.ok) {
const json = await response.json() //
return json
} else {
// what if `response` contains error messages in json format?
return Promise.reject(new Error('Unknown Error'))
}
})
}
它工作正常。问题出在这个片段上
return fetch(endpoint, config as any).then(async (response) => {
if (response.ok) {
const json = await response.json()
return json
} else {
// what if `response` contains error messages in json format?
return Promise.reject(new Error('Unknown Error'))
}
})
如果响应不正常,它会拒绝一个通用的Error. 这是因为默认情况下,window.fetch只有在实际网络请求失败时才会拒绝承诺。但问题是,即使response不正常,它仍然可能会出现json格式错误消息。这取决于后端实现细节,但有时您可以通过response.json(). 现在这个用例没有包含在我构建的包装器中。
所以我想知道我将如何能够解释这一点?我想你可以做类似的事情
fetch(endpoint, config as any).then(async (response) => {
if (response.ok) {
const json = await response.json()
return json
} else {
try {
const json = await response.json()
return Promise.reject(json)
} catch {
return Promise.reject(new Error('Unknown Error'))
}
}
})
但我想知道是否有一些更优雅的方法来做到这一点?
最后,我非常了解像 Axios 这样的库。我建造这个部分是为了满足我的求知欲。
顺便说一句,一个稍微不相关的问题,但我想知道这两个是否等效
if (response.ok) {
const json = await response.json()
return json
}
if (response.ok) {
return response.json()
}
有人将我的问题标记为与此问题重复。事实上,它们并不相同。我没有做出与该问题相同的假设,即 API 调用在成功和失败时都返回 JSON 数据。我的问题是在我们不能做出这样的假设的情况下,我们究竟应该怎么做。
回答
响应不是ok不会阻止您将其主体作为 JSON 使用,因此您的最后一个片段确实应该如何处理。
现在您要求“更优雅”的东西,它可能不会更优雅,但编写相同内容的冗余方式将是:
fetch(endpoint, config as any).then(async (response) => {
if (response.ok) {
return response.json(); // there is no need to await the return value
}
else {
const err_message = await response.json() // either we have a message
.catch( () => new Error( "Unknown Error" ) ); // or we make one
return Promise.reject( err_message );
}
})
关于最后一个问题,是的,两者是等价的,await版本通过微任务队列再进行一次往返并使您的代码更长一些,但对于所有重要的事情,我们可以说它们是相同的。
THE END
二维码