I have this function that collects JSON data from an API endpoint:
export const getDataAPI = (token_id) => {
const url = `https://api.url.com/tokens/` token_id;
const options = {method: 'GET', headers: {Accept: 'application/json'}};
const request = fetch(url, options)
.then(response => { if (response.status === 200) {
return response.json();
} else if ([404, 429, 500].includes(response.status)) {
return response.status;
} else {
return response.json()
.then(json => {
console.log("Error: getDataAPI response status", response.status);
throw json;
})
}
})
.catch(error => { throw error; });
return Promise.resolve(request);
};
I have collected over 1.3M records with this function. I would like to catch any unexpected problems so I can gracefully pause for a few seconds and try again. But I came across 2 errors that were not sent to the .catch clause. Even if response
is empty / null / undefined, I would expect at least to see the output of console.log("Error: getDataAPI response status", response.status);
These errors only happened once each.
undefined:1
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at Response.json (file:///home/user/node_modules/node-fetch/src/body.js:149:15)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async file:///home/user/path/to/file.mjs:94:20
file:///home/user/node_modules/node-fetch/src/index.js:108
reject(new FetchError(`request to ${request.url} failed, reason: ${error.message}`, 'system', error));
^
FetchError: request to https://api.url.com/tokens/29727608 failed, reason: read ECONNRESET
at ClientRequest.<anonymous> (file:///home/user/node_modules/node-fetch/src/index.js:108:11)
at ClientRequest.emit (node:events:526:28)
at TLSSocket.socketErrorListener (node:_http_client:442:9)
at TLSSocket.emit (node:events:526:28)
at emitErrorNT (node:internal/streams/destroy:157:8)
at emitErrorCloseNT (node:internal/streams/destroy:122:3)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
type: 'system',
errno: 'ECONNRESET',
code: 'ECONNRESET',
erroredSysCall: 'read'
}
I don't understand why these errors were not caught by the function. Can someone please explain this?
How can I fix the function so it also catches this sort of errors?
What is the output I should be looking for to identify these errors,
SyntaxError
andFetchError
? Is there a variable to monitor for error codes for example?
CodePudding user response:
I would expect at least to see the output of console.log("Error: getDataAPI response status", response.status);
That code isn't in a catch clause, it's in a then
clause.
return response.json()
.then(json => {
console.log("Error: getDataAPI response status", response.status);
throw json;
})
Your catch
is simply rethrowing:
.catch(error => { throw error; });
Which will give you an uncaught error.
You need to log/handle the error in the catch, not the then
clause:
export const getDataAPI = (token_id) => {
const url = `https://api.url.com/tokens/` token_id;
const options = {method: 'GET', headers: {Accept: 'application/json'}};
const request = fetch(url, options)
.then(response => { if (response.status === 200) {
return response.json();
} else if ([404, 429, 500].includes(response.status)) {
return response.status;
} else {
console.log("Error: getDataAPI response status", response.status);
// you can swallow the error here if you want, or try to parse it anyway
return response.json()
}
})
.catch(error => {
console.log('Handling error', error);
throw error;
});
// wrapping the request in a Promise.resolve is also unnecessary
// return Promise.resolve(request);
return request;
};
CodePudding user response:
I'm not sure but are you sure that the API returns a well formatted JSON ?
Or could you surround with try catch the return response.json() ?
CodePudding user response:
Yes I didn't saw that, the .then should goes in a different place ..
export const getDataAPI = (token_id) => {
const url = `https://api.url.com/tokens/` token_id;
const options = {method: 'GET', headers: {Accept: 'application/json'}};
const request = fetch(url, options)
.then(response => { if (response.status === 200) {
return response.json();
} else if ([404, 429, 500].includes(response.status)) {
return response.status;
} else {
return response.json()
}
}).then(json => {
console.log("Error: getDataAPI response status", response.status);
throw json;
}).catch(error => { throw error; });
return Promise.resolve(request);
};