I'm struggling for 2 days on this one so I try asking here:
I have a nodejs script using node-fetch to make queries ton an API. However, I've tried adding catch blocks everywhere but it seems I didn't suceeded in ahndling the error.
Here is my function:
fetchUrl.get = async (url, params = false, headers = false) => {
let defaultOptions = {
method: "GET",
};
let finalUrl = new URL(url);
Object.keys(params).forEach((key) =>
finalUrl.searchParams.append(key, params[key])
);
let finalHeaders = {};
if (headers != null && headers != false && Object.keys(headers).length > 0) {
Object.keys(headers).forEach((headerKey) => {
finalHeaders[headerKey] = headers[headerKey];
});
}
defaultOptions["headers"] = finalHeaders;
let result = null;
try {
result = await fetch(finalUrl, defaultOptions)
.then((res) => {
if (res.status == 200) {
return {
success: true,
text: res.text(),
};
} else {
console.log("ERROR during Fetch: " res.status);
console.error(finalUrl);
console.error(params);
res.text().then((err) => {
console.error(err);
});
return {
success: false,
};
}
})
.then((resParsed) => {
if (resParsed.success) {
return resParsed.text;
} else {
return false;
}
});
} catch (err) {
throw err;
}
return result;
};
And this is the error I get:
(node:2272) UnhandledPromiseRejectionWarning: FetchError: request to http://gdsfdfs.com/ failed, reason: getaddrinfo ENOTFOUND gdsfdfs.com
at ClientRequest.<anonymous> (file:///home/kashnars/pearlv2/node_modules/node-fetch/src/index.js:108:11)
at ClientRequest.emit (events.js:375:28)
at Socket.socketErrorListener (_http_client.js:475:9)
at Socket.emit (events.js:375:28)
at emitErrorNT (internal/streams/destroy.js:106:8)
at emitErrorCloseNT (internal/streams/destroy.js:74:3)
at processTicksAndRejections (internal/process/task_queues.js:82:21)
(node:2272) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 50)
I know the URL is wrong, it's just for testing purposes. I need to catch the error.
Someone having the solution?
Thanks in advance,
CodePudding user response:
If you rethrow the exception after catching it, then it makes the caller error out (in your case ClientRequest.emit
) so either dont rethrow it, or handle it in the caller.
That being said you should not use await
and then
simultaneously, use one of them (I strongly advise for await
).
Basically your code could be simplified to this:
try {
const result = await fetch(finalUrl, defaultOptions);
return result.status == 200 ? result.text() : false;
}
catch(e) {
console.log(e);
}
CodePudding user response:
The issue is that you throw an error, which is a Promise rejection in an async function
The calling function needs to handle the rejection
Now, since all you do in the catch
is rethrow the error, no need to use try/catch at all
More simplifiction of your code is possible - but, basically, from the await
it should go like
const res = await fetch(finalUrl, defaultOptions);
if (res.status == 200) {
return res.text();
}
console.log("ERROR during Fetch: " res.status);
console.log(finalUrl);
console.log(params);
const err = await res.text();
console.error(err);
return false;
with no try/catch
Alternatively, if you want this function to handle the network error, and return false, just like when status !== 200
try {
const res = await fetch(finalUrl, defaultOptions);
if (res.status == 200) {
return res.text();
}
console.log("ERROR during Fetch: " res.status);
console.log(finalUrl);
console.log(params);
const err = await res.text();
throw err;
} catch(err) {
console.error(err);
return false;
}
as a bonus, the code above the try {
or await fetch
can be simplified to
fetchUrl.get = async (url, params = false, headers = false) => {
const defaultOptions = {
method: "GET",
headers: {...(headers ?? {}) }
};
const finalUrl = new URL(url);
Object.entries(params ?? {}).forEach(([key, value]) => {
finalUrl.searchParams.append(key, value)
});