Reputation: 20571
Redux docs suggest to have 3 different actions per AJAX request. For example for Login they would be:
LOGIN_REUQEST
LOGIN_FAILURE
LOGIN_SUCCESS
But I have problem with catching all errors that can be thrown by fetch
.
In redux docs I found this example:
return fetch(`https://www.reddit.com/r/${subreddit}.json`)
.then(
response => response.json(),
// Do not use catch, because that will also catch
// any errors in the dispatch and resulting render,
// causing an loop of 'Unexpected batch number' errors.
// https://github.com/facebook/react/issues/6895
error => console.log('An error occured.', error)
)
.then(json =>
// We can dispatch many times!
// Here, we update the app state with the results of the API call.
dispatch(receivePosts(subreddit, json))
)
}
But I see several problems in it:
I ended up this this code, but still it won't handle case #1 (because of React issue - see comment in above code):
fetch('/api/auth/signin', {...}),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text/plain, */*',
}
})
.then ( response =>
response.json().then(json => {
if (response.ok) {
dispatch(loginSuccess(json))
} else {
dispatch(loginFailure(json.errMsg))
}
})
)
Can you please give me any example which handles all possible errors with AJAX request using fetch. Many tutorial and open-source projects just ignoring it.
Upvotes: 0
Views: 1346
Reputation: 322
async function fetchLists(url, token, userName, etag, dataToUpdate) {
var responseJSON;
try {
let response = await fetch(url,
{
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Access-Token': token,
'X-Key': userName,
'If-None-Match': etag
}
}
);
switch (response.status) {
case 200:
var data = await response.json();
var dataType = getListForUpdate(dataToUpdate);
responseJSON = {
action: dataType,
message: UPDATE_DATA,
response: response,
responseJSON: data
}
break;
case 304:
var dataType = getListUptoDate(dataToUpdate);
responseJSON = { action: dataType, message: DATA_UPTO_DATE };
break;
case 404:
responseJSON = { message: NOT_FOUND };
break;
case 500:
responseJSON = { message: SERVER_ERROR };
break;
case 401:
case 402:
responseJSON = { message: INVALID_CREDENTIALS };
break;
}
// console.log(response);
} catch (err) {
// console.log(err);
responseJSON = { message: NETWORK_REQUEST_FAILED };
// console.log(responseJSON);
}
return responseJSON;
}
This code structure maybe able to solve your problem. I have recorded all the responses and left catch for network request failures. Comment if you don't understand any of it.
Hope it helps.
Upvotes: 1
Reputation: 6652
You don't need .catch()
to handle offline errors. The second argument to .then()
, the error callback, will catch offline (no internet connection) errors.
And, handling responses that are not 200 is straightforward:
fetch({...})
.then(
response => {
if (response.status !== 200) {
dispatch(loginFailed(response.json()));
return Promise.reject();
} else {
return response.json();
}
},
error => {
dispatch(loginFailed(error.json()));
return Promise.reject();
}
)
.then(json => {
dispatch(loginSuccess(json));
});
Upvotes: 2