I am writing a simple wrapper around 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'))
}
})
}
It works fine. The problem is with this snippet:
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'))
}
})
If response
is not ok, it rejects with a generic Error
. This is because by default, window.fetch
will only reject a promise if the actual network request failed. But the issue is that, even if response
is not ok, it might still be able to have error messages in json
format. This depends on the backend implementation details but sometimes you are able to get the error messages in the response body by response.json()
. Now this use case is not covered in the wrapper I built.
So I wonder how I am going to be able to account for that? I guess you can do something like
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'))
}
}
})
I wonder if there is some more elegant way to do that?
Lastly, I am very aware of libraries like Axios. I built this partly to satisfy my intellectual curiosity.
By the way, a lightly unrelated question but I wonder if the following snippets are equivalent?
if (response.ok) {
const json = await response.json()
return json
}
if (response.ok) {
return response.json()
}