In a locally run Node.js script, this works when status is 200:
// module file
import fetch from "node-fetch";
export const getJSON = () => {
const url = 'https://api.somesite.com/api/v0/etc';
const options = {method: 'GET', headers: {Accept: 'application/json'}};
const request = fetch(url, options)
.then(response => response.json())
.catch(err => console.log("somesite:", err));
return Promise.resolve(request);
};
// execution file
import { getJSON } from './libs/api_requests.mjs';
console.log("func call", await getJSON());
But the fetch
also works without triggering the .catch
logic when the response status is 4xx or 5xx (see for example this answer).
Execution doesn't break and I actually receive an error message when the function is called as if that would be the correct, normal result - as the output of response.json()
.
This message is in plain English, something like "error: 'Incorrect path. Please check https://www.somesite.com/api/'".
I would like to preserve/display this error message, only I would like to catch it within the function getJSON
in the module file, instead of having to wrap some logic around it at the destination, potentially repeating the same code multiple times everywhere the function is called, instead of dealing with the issue just once at the source.
So I modified the .then
clause like this, which also works:
.then(response => { if (response.ok) { // .ok should be status 200 only, I suppose
return response.json();
} else { throw new Error(response.status) }
This now triggers the .catch
clause as intended, displaying "Error: 404 [etc]". Except what I would like to throw is the original error message "Incorrect path [etc]" and that I could not do. I tried
.then(response => { if (response.ok) {
return response.json();
} else { throw new Error(response.json()) } // somesite: Error: [object Promise]
.then(response => { if (response.ok) {
return response.json()
} else { throw new Error(Promise.resolve(response.json())) } // somesite: Error: [object Promise]
.then(response => { if (response.ok) {
return response.json()
} else { throw new Error(return response.json()) } // SyntaxError: Unexpected token 'return'
.then(response => { if (response.ok) {
return response.json();
} else { throw new Error(Promise.resolve(request)) } // somesite: Error: [object Promise]
I guess I need to resolve the response.json()
promise as if all was ok, but how to do that?
I also had a look at the request
object with console.dir(request, { depth: null })
to see if I could extract the error message from there, but I couldn't find it and the object still contained many unexpanded elements like [Function: onerror]
or [Function: onclose]
for example.
Try response.text()
instead of response.json()
when the status code is 400
or 500
.
In my experience, the error messages are typically returned by the text
callback.
See this answer to a similar question.
Edit:
Added the following code, suggested by OP.
.then((response) => {
if (response.ok) {
return response.json();
}
else {
return response.text()
.then((text) => {
throw(text);
// if the error is an object and you just want to display some elements:
throw(JSON.parse(text));
});
}
})
.catch((err) => {
// in case you want to log the error
console.log("somesite: ", err));
return new Error("somesite: " + err);
});