A fetch API request will only fail if there is a network or server error. So for example, if I execute the following code, assuming it went through the try
block without an error, I will have a valid populated 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!')
}
I am handling res
to show the users the necessary error
or success
message using the flashResponseToUser(res)
function. Since res.json()
returns a Promise
, flashResponseToUser
has to be an async function.
const flashResponseToUser = async(res) => {
const jsonRes = await res.json() // Get data from response
console.log(jsonRes)
}
I want to know:
res.json()
return a Promise
since at this point the response has already been received by the client?Promise
returned by res.json()
fail?flashResponseToUser(res)
also need to be wrapped within a try-catch
block since I am using res.json()
?Using async/awaitYou start by specifying the caller function as async and then use await to handle the promise. Because of the await keyword, the asynchronous function pauses until the promise is resolved. The Response object is assigned to response once the request completes.
json() is a method on the Response object that lets you extract a JSON object from the response. The method returns a promise, so you have to wait for the JSON: await response.
Since res. json() returns a Promise , flashResponseToUser has to be an async function.
To get JSON from the server using the Fetch API, you can use the response. json() method. The response. json() method reads the data returned by the server and returns a promise that resolves with a JSON object. If you are expecting a text, call the response.
Why does res.json() return a Promise since at this point the response has already been received by the client?
fetch
returns a Response object. This indicates that the headers of the response have been received, but does not necessarily mean that the whole response has been received - imagine, for example, when you load a huge page. It's not exactly the same thing, but you'll receive the headers and the browser will start to load the response even though there's still more to download. The Response object provides the headers and a way to handle still-incoming data.
Under what conditions would the Promise returned by res.json() fail?
It might fail if the response wasn't in proper JSON format. For example, if the plain text of the response was Internal Server Error
, which isn't JSON. Here's an example:
(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()?
If you wanted to be perfectly safe, yes. But, in most situations, it's easiest just to catch in one place, where you can handle the error. Instead of handling possible errors at every step of the process, you might handle the error just once, in the consumer, eg:
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!')
})
(assuming that flashResponseToUser
will never throw, if provided with an expected object. If flashResponseToUser
might throw anyway, you can separate out the .catch
es to distinguish network errors from other runtime errors)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With