I've written the code below in an attempt to gracefully handle both connection errors and non-OK HTTP status codes, as well as retrying in some cases.
For some reason, that I can't deduce by reading the code, in case of a bad HTTP status code, a Promise is passed as argument to the function given to catch
(I know ’catch()` itself returns a Promise). Ie.
testGet(500).catch(res => console.log(res))
will print [object Promise]
Can anyone tell me where I throw a Promise object in the code below? Or, in other words, why handleStatusError
returns a Promise, when it appears to be given a Response (which it returns)?
// **** Behavior ****
//
// HTTP error 4xx: Don't retry (we messed up)
// HTTP error 5xx: Retry (the server messed up)
// Connection error: Retry (ITU's wifi messed up)
export function testGet(code) {
var url = "http://httpstat.us/" + code
console.log("Fetching '" + url + "'")
return httpGet(url, 2);
}
export function httpGet(url, numRetries) {
var options = {
mode: 'cors',
headers: {
'Accept': 'application/json',
}
};
return fetchRetry(url, options, numRetries);
}
export function httpPost(url, body, numRetries) {
var options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
};
return fetchRetry(url, options, numRetries);
}
function fetchRetry(url, options, numRetries) {
numRetries = numRetries || 1;
return httpRequest(url, options).catch(error => {
if (numRetries <= 1 || error.retry !== true) {
throw error.json();
} else {
return fetchRetry(url, options, numRetries - 1);
}
});
}
function httpRequest(url, options) {
return fetch(url, options)
// Handle connection/network error
.catch(error => {
error.retry = true;
error.json = () => error.message || "Network/connection error";
throw error;
})
.then(response => {
if (response.ok) return response.json();
// Handle HTTP status code error
else throw handleStatusError(response);
});
}
const handleStatusError = response => {
response.retry = false;
// Check status code
var status = response.status;
if (status >= 400 && status < 500) { // User error
response.retry = false;
} else if (status >= 500 && status < 600) { // Server error
response.retry = true;
}
return response;
}