I want to bullet-proof some code which takes user input and attempts to fetch data from a URL.
I have something like the following:
fetch(url)
.then(response=>{
console.log(response.ok);
response.text();
})
.catch(error=>console.log(error));
There’s more afterwards in the actual code.
If I enter something like http://rubbish I catch a TypeError which I can handle. If I enter something like rubbish (without the http:// protocol), I get an error like :
GET file:///…/rubbish net::ERR_FILE_NOT_FOUND
and then get my TypeError. The actual error occurs on the first line of the code above, before the catch() block.
What is the correct way to handle an error like this?
I’m doing this in an Electron App, so one thing I don’t have to worry about is browser compatibility.
You could potentially execute different logic in the catch block depending on the type of error. For example:
fetch(url)
.then(response=>{
console.log(response.ok);
response.text();
})
.catch(
if (err instanceof TypeError) {
// Handle this normally
} else {
// Execute other logic depending on the type of error you are receiving
}
);
Hope this helps, good luck :)
Related
Please allow me to ask a possibly easy question. Can someone tell me where the message property of argument err in catch function at the end of fetch API came from? For example in the code snippet below
fetch('exmaple.json')
.then(response => response.json())
.then(json => randomlyMadeFunction())
.catch(err => console.log('Fetch problem: ' + err.message));
I know fetch returns a Promise, and at the end catch function takes rejected reason as parameter, in this case err. I search many articles on MDN js reference, but I couldn't figure out where the property message of err came from. Any explanation or hint would be much appreciated.
Thanks in advance.
If an error occurs during fetch, either a AbortError or a TypeError will be passed to the catch callback, see fetch Exceptions:
AbortError The request was aborted due to a call to the AbortController method abort() method.
TypeError The specified URL string includes user credentials. This information should instead be provided using an Authorization
header.
TypeErrors are Errors and therefore have a message property, see Error.prototype.message.
When using an api I often find myself with a rather complicated error object.
Depending on the API that I am using the error texts are quite helpful and I would actually sometimes like to display them directly to the user. The problem, of course, is that the error objects can look quite differently so it would be very verbose to go through them and pick individual objects in case they exists (dependant on the status code of the error).
Is this just the nature of the error object or is there a better way to do this?
What I do to handle API calls that end up with error is this:
try {
const response = await axios.post("Your URL");
// Your code to handle the result
} catch (error) {
console.log(error.response.data.error)
// Code to display the error to the user
}
error.response.data.error is the actual error message sent from the server, not the error code
everyone!
I got a problem: I'm trying to validate registration form. Totally, it works ok, but I need to validate form via server. In my case, for example, I need to figure out if email is already taken.
I tried to fetch and async/await syntax, but problem is still the same:
DOMException: "The operation was aborted. "
The way I understand it right now is readableStream (what actual response body is) is locked. So the wrong error is thrown, and I cannot get server response.
try {
const response = await fetch(options.url, options.requestOptions);
const body = await response.json();
if (options.modifyDataCallback instanceof Function) {
body.data = options.modifyDataCallback(body.data);
}
return body.data;
} catch (error) {
throw error;
}
How do I see the solution? I send request and recieve some server error like
code: email_in_use
message: Email '...' is already in use.
Then I need to throw error and catch it in other place in order to show corresponding error message to client.
In browsers network tab I do receive what I want to receive, but can't get the same JSON-response in my code.
Google chrome provided more information: net::ERR_HTTP2_PROTOCOL_ERROR 200.
And the problem was on backend. It is written in C# and API method returned Task. The problem was solved by adding async/await for this method.
To make a long story short:
I'm building node app which making a request with https (the secure version of http). Whenever I miss-configure my request options, I'm having this error:
Node.js Hostname/IP doesn't match certificate's altnames
Great... except of the fact that the entire request code is wrapped with a valid try..catch block (which works just fine.. checked that already). The code is basically something like this:
try
{
https.request(options, (response) =>
{
// no way I making it so far this that error
}).end();
}
catch(ex)
{
// for some reason.. I'm not able to get here either
}
What I intend to do is to simply handle that error within my try..catch block
After reading some posts I've learned that this behavior is mainly because the tls module is automatically process the request and therefore making this error - this is a nice piece of information but it doesn't really help me to handle the exception.
Some other suggested to use this option:
rejectUnauthorized: false // BEWARE: security hazard!
But I rather not... so.. I guess my questions are:
Handling an error with a try..catch block should work here..right?
If not - is this behavior is by-design in node?
Can I wrap the code in any other way to handle this error?
Just to be clear - I'm not using any third-party lib (so there is no one to blame)
Any kind of help will be appreciated
Thanks
You need to add an 'error' event handler on the request object returned by https.request() to handle that kind of error. For example:
var req = https.request(options, (response) => {
// ...
});
req.on('error', (err) => {
console.log('request error', err);
});
req.end();
See this section in the node.js documentation about errors for more information.
I am getting error with status 302
But while trying to log error in catch I am getting 200
post(url, data, successCallBack, errCallback) {
return this.http.post(apiDomain + url, JSON.stringify(data), {
headers: this.headers
}).catch(this.handleError).subscribe(
(res) => {
successCallBack(res.json());
},
(err) => {
errCallback(err);
}
);
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status;
console.log(error.status); // log is 200
console.log(error)
console.error(errMsg);
return Observable.throw(errMsg);
}
Requirement I want to send another post call on redirect URL redirects.
How to get Redirect URL.
Need help.
Late answer I know, but for anyone stumbling across this.
The short answer is you can't as the browser handles 302's itself and won't tell angular anything about that. What you can do is set-up an interceptor style class that monitors what is going on.
Google for angular2 http interceptor or similar, it's a little beefier than your example above and can monitor every XHR connection. An example is here:
https://www.illucit.com/blog/2016/03/angular2-http-authentication-interceptor/
What this now allows is that any connection will come through your interceptor. As we won't be able to monitor 302s, we have to think about what might happen. For example in my example the request suddenly changes the url to something with my auth in it.
Great so my 1st bit of pseudo code would be:
if (response.url.contains('my-auth string')) {
redirect....
}
I can also see on the headers provided that instead of application/json I've suddenly gone to text/html. Hmm, that's another change I can check for:
if (response.url.contains('my-auth string') && response.headers['content-type'] == 'text/html') {
redirect....
}
You may have other parameters you can check, however these were good enough to detect a redirect for me. Admittedly this is with respect to being redirected to login and not another example, hopefully you get enough distinct changes check for you to decide whether you have got a 302.