I want to display error message from my API, problem is that I can't reach that error if I check for response.ok
, it returns Fetch error, not the one from API..
If I don't use if(response.ok)...
it returns the error from API but it dispatches the success action.
Here is the example, login action:
export const signIn = data => dispatch => {
dispatch({
type: SIGN_IN
})
fetch(API_URL+'/login', {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(data),
})
.then( response => {
if (!response.ok) { throw response }
return response.json() //we only get here if there is no error
})
.then( json => {
dispatch({
type: SIGN_IN_SUCCESS, payload: json
}),
localStorage.setItem("token", 'Bearer '+json.token)
localStorage.setItem("user", JSON.stringify(json.user))
})
.catch( err => {
dispatch({
type: SIGN_IN_FAILED, payload: err
})
})
}
This is the code for action that dispatches the right message but as success action, not as failed one..
export const signIn = data => dispatch => {
dispatch({
type: SIGN_IN
})
fetch(API_URL+'/login', {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(data),
})
.then( response => response.json())
.then( json => {
dispatch({
type: SIGN_IN_SUCCESS, payload: json
}),
localStorage.setItem("token", 'Bearer '+json.token)
localStorage.setItem("user", JSON.stringify(json.user))
})
.catch( err => {
dispatch({
type: SIGN_IN_FAILED, payload: err
})
})
}
To get the status code of an HTTP request made with the fetch method, access the status property on the response object. The response. status property contains the HTTP status code of the response, e.g. 200 for a successful response or 500 for a server error.
The Promise returned from fetch() won't reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.
According to the fetch() MDN, the Promise object returned by the fetch() call is rejected (throws an error) only when "a network error is encountered." This means that fetch() Promises do resolve despite encountering client-side HTTP errors such as 404 and do not throw errors during the fetch.
The Fetch API provides an interface for fetching resources (including across the network). It will seem familiar to anyone who has used XMLHttpRequest , but the new API provides a more powerful and flexible feature set. Note: This feature is available in Web Workers.
Follow me on twitter. I share quick tips, my reading list and also about free workshop and webinars around web and mobile development everyday. Fetch API is very powerful. We can easily send Ajax request using browser fetch API. But it has its own disadvantages too. One major disadvantage is error handling when using fetch.
Per MDN, the fetch () API only rejects a promise when “a network error is encountered, although this usually means permissions issues or similar.” Basically fetch () will only reject a promise if the user is offline, or some unlikely networking error occurs, such a DNS lookup failure.
The fetch .then () callback is passed the HTTP response object when the request is completed, the function checks if the response type is JSON before parsing the response body with the response.json () method, because calling response.json () will cause an error if the response doesn't contain JSON data.
“a network error is encountered, although this usually means permissions issues or similar.” Basically fetch () will only reject a promise if the user is offline, or some unlikely networking error occurs, such a DNS lookup failure. then, you can use this part of code to use non-network error handlings and make your code more readable
With the following solution one can handle JSON API error, Generic API error and Generic fetch error
fetch("api/v1/demo", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"data": "demo"
})
})
.then(response => {
if (!response.ok) {
return Promise.reject(response);
}
return response.json();
})
.then(data => {
console.log("Success");
console.log(data);
})
.catch(error => {
if (typeof error.json === "function") {
error.json().then(jsonError => {
console.log("Json error from API");
console.log(jsonError);
}).catch(genericError => {
console.log("Generic error from API");
console.log(error.statusText);
});
} else {
console.log("Fetch error");
console.log(error);
}
});
In order to extract API message from server in case of some error, you have to use the following idiom (which doesn't lie on the surface though), see link
fetch("http://localhost:8090/test/error", {
method: 'GET',
headers: {
'Accept': 'application/json'
}
})
.then(result => {
//Here body is not ready yet, throw promise
if (!result.ok) throw result;
return result.json();
})
.then(result => {
//Successful request processing
console.log(result);
}).catch(error => {
//Here is still promise
console.log(error);
error.json().then((body) => {
//Here is already the payload from API
console.log(body);
});
})
Verbose - yes!, but does exactly what is needed.
according to This Article :
Per MDN, the
fetch()
API only rejects a promise when“a network error is encountered, although this usually means permissions issues or similar.”
Basically
fetch()
will only reject a promise if the user is offline, or some unlikely networking error occurs, such a DNS lookup failure.
then, you can use this part of code to use non-network error handlings and make your code more readable
function handleErrors(response) {
if (!response.ok) throw new Error(response.status);
return response;
}
fetch("API URL")
// handle network err/success
.then(handleErrors)
// use response of network on fetch Promise resolve
.then(response => console.log("ok") )
// handle fetch Promise error
.catch(error => console.log(error) );
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