Reputation: 6823
We are finding that occasionally our .fetch command is returning a 404. Even though the file exists and is hit regularly sometimes it's receiving a 404.
window.fetch('/category/somepage', {
credentials: 'same-origin',
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(app.addAntiForgeryToken(postData))
})
.then(function(response) {
if (response.ok) {
return response.json();
}
throw new Error('Network response was not ok');
})
.then(result => {
if (result.Status === 'OK') {
//...
}
})
At the moment it is being caught with the throw new Error
.
As we need this to resolve, what is the best way to force try this again until the page is hit? Should we show a button for retry or is there a way to loop this? I'm not sure why this would even throw a 404 as the file definitely exists all the time.
Upvotes: 0
Views: 1401
Reputation: 1074295
The classic thing to do here is to retry the operation, because network communications can be unreliable, particularly on mobile devices. But transient 404s are a different issue, and point to a problem with the web server that may need separate diagnosis. (For instance: If it's a cluster of web servers acting as a single endpoint, one of them may be misconfigured and thus not finding a resource the rest of them can find.)
But for transient failures, the classic thing is a retry:
function fetchJSONWithRetry(input, init, retries = 10) {
return fetch(input, init)
.then(function(response) {
if (response.ok) {
return response.json();
}
throw new Error('Network response was not ok'); // I usually use `new Error("HTTP status " + response.status)`
})
.catch(error => {
if (retries <= 0) {
throw error;
}
return fetchJSONWithRetry(input, init, retries - 1);
});
}
used like this:
fetchJSONWithRetry('/category/somepage', {
credentials: 'same-origin',
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(app.addAntiForgeryToken(postData))
})
.then(result => {
if (result.Status === 'OK') {
// ...
}
})
.catch(error => {
// All retries failed, handle it
});
(input
and init
are the names used by the spec for fetch
, so that's what I used above.)
Upvotes: 3