How to catch the error when making fetch api request? [duplicate] - javascript

This question already has answers here:
How to handle HTTP code 4xx responses in fetch api
(4 answers)
Handle a 500 response with the fetch api
(2 answers)
try..catch not catching async/await errors
(1 answer)
Closed 2 years ago.
I am sending request with fetch api and make action according to the result is correct or it includes error.
my service code:
LoginUser(user: User) {
return fetch("http://localhost:8080/login", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify(user)
});
}
and my then-catch code which calls the above one is:
async loginUser() {
let response = await this._service.LoginUser(this.user)
.then(response => {return response.json()})
.then(response => {this._router.navigate(['/mainpage'])})
.catch(error => {alert(error)});
}
Whether the response is coming with code 500 Internal Server Error still it is redirecting to /mainpage and does not recognise the error. How can I fix this problem ?

When a fetch request comes back with an error code from the server, the catch of the promise is not executed, the then is. The catch is only executed if there is a network failure. See the fetch docs:
The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.
What you need to do is, inside your then, check response.ok. If response.ok == false, then the request returned an error. You can find info about this error in response.status and response.statusText.

If you are using async await you shouldnt have to chain on .thens like you are resolving a promise.
I adjusted your code and wrapped it in a try/catch, the try/catch error will handle an error from a non response however you will need to check your server response for errors itself
async loginUser() {
try {
let response = await this._service.LoginUser(this.user)
// Check your response for error this may not be response.error
if (response.error) {
// Handle error
alert(error)
} else {
// Navigate on success
this._router.navigate(['/mainpage'])
}
} catch (err) {
alert(err)
}
}

Related

Fetch fails when exceeding a certain execution time even-though using proper CORS headers

I have been stuck with a weird issue with CORS for quite some time now. To explain the setup I have a frontend JS snippet (including fetch API call to my own server) which I want to use as an embed code snippet other web applications can use. (ex: kind of like google analytics)
// JS snippet to copy to an unknown website
<script>
// extract data and add to the body
const extracted_data = {}
fetch("https://api.xxxx.com/xxxxxx/create", {
method: "POST",
mode: 'cors',
body: JSON.stringify(extracted_data),
referrer: "origin",
headers: {
'Content-Type': 'application/json',
},
})
.then(function (response) {
// The API call was successful!
if (response.ok) {
return response.json();
} else {
return Promise.reject(response);
}
})
.then(function (data) {
// This is the JSON from our response
console.warn("Successfull!", data);
alert("Success:" + JSON.stringify(data));
})
.catch(function (err) {
// There was an error
console.warn("Something went wrong ->", err);
alert("error:" + err.message);
});
</script>
The problem is even if I have set my fetch API as below and the correct CORS headers are in my preflight response from my API it works only when the API call resolves immediately. If the API takes more time Fetch throws this common error even if the preflight is successful.
TypeError: Failed to fetch
I verified it using adding the below code to my API. Then it stops working and throws the above error. When I don't have any time taking functions inside my API call it works without errors.
// 10 sec delay to check async behavior of the API
await new Promise(resolve => setTimeout(resolve, 10000));
Any recommendations on how I should proceed to resolve this?

Promise doesn't reject [duplicate]

This question already has answers here:
How to handle HTTP code 4xx responses in fetch api
(4 answers)
Fetch: reject promise and catch the error if status is not OK?
(11 answers)
Closed 1 year ago.
Here is the code:
await fetch("http://localhost:3000/login", {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
login: name,
password: pass
}),
})
.then(async() => {
await AsyncStorage.setItem('Login', name)
})
.catch(err => alert(err));
When I try to intentionally make a mistake in order to test the logging process, I get the error in the "Network" tab of my browser, but my website thinks that everything is fine and it executes the .then() code, even though it obviously shouldn't do that, because the Promise is rejected (it says POST http://localhost:3000/login 400 (Bad Request) in the console).
I tried a different code
.then(async () => {
await AsyncStorage.setItem('Login', name)
}, (reason) =>
alert(reason)
);
But it too doesn't work the way I want, it should execute this part (reason) => alert(reason)).
What's the solution?

How to avoid the CORS error without telling fetch "mode: "no-cors"? [duplicate]

This question already has answers here:
XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header
(11 answers)
Closed 3 years ago.
My initial question (JavaScript fetch API data and use XML response as an object) was marked a duplicate of SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data using fetch, so I am asking another question, building on top of what I learned (or assume):
I have a cors error when using fetch() in JS to call an API if I don't define "{ mode: "no-cors" }". I also get the error when I run a local server! When I do define no-cors, I don't get the cors error, but the response seems to be empty.
How to avoid the cors error and get a response?
My code is the following:
async function apiCall() {
const url =
"https://service.runmyaccounts.com/api/latest/clients/apitest/invoices?api_key=d1bvbxkI8f1bnMBJ4sZiC-xupl4fOEzf"; // yes this is ok to publish as it is in the api documentation and just a test account
try {
const response = await fetch(url, {
headers: {
"Content-Type": "text/xml"
}
});
const data = await response.text();
console.log(data);
//return data;
} catch (err) {
console.log(err);
}
}
apiCall();
It seems to be hacked but... working: Using fetch with proxy
var proxy_url = 'https://cors-anywhere.herokuapp.com/';
var main_url = 'https://service.runmyaccounts.com/api/latest/clients/apitest/invoices?api_key=d1bvbxkI8f1bnMBJ4sZiC-xupl4fOEzf';
fetch(proxy_url + main_url)
.then(response => response.text())
.then(data => console.log(data));

Fetch API: Can 'await res.json()' fail after a completed request?

A fetch API request will only fail if there is a network or server error. So for example, if I execute the following code, assuming it went through the try block without an error, I will have a valid populated res.
try {
const res = await fetch('/createurl', {
method: 'POST',
body: 'testData',
headers: {
'Content-Type': 'application/json'
}
})
if (res.ok) {
alert('Resource created!')
} else {
alert('Error creating resource!')
}
flashResponseToUser(res)
} catch(e) {
alert('A server or network error occurred during the request!')
}
I am handling res to show the users the necessary error or success message using the flashResponseToUser(res) function. Since res.json() returns a Promise, flashResponseToUser has to be an async function.
const flashResponseToUser = async(res) => {
const jsonRes = await res.json() // Get data from response
console.log(jsonRes)
}
I want to know:
Why does res.json() return a Promise since at this point the response has already been received by the client?
Under what conditions would the Promise returned by res.json() fail?
Does the code within flashResponseToUser(res) also need to be wrapped within a try-catch block since I am using res.json()?
Why does res.json() return a Promise since at this point the response has already been received by the client?
fetch returns a Response object. This indicates that the headers of the response have been received, but does not necessarily mean that the whole response has been received - imagine, for example, when you load a huge page. It's not exactly the same thing, but you'll receive the headers and the browser will start to load the response even though there's still more to download. The Response object provides the headers and a way to handle still-incoming data.
Under what conditions would the Promise returned by res.json() fail?
It might fail if the response wasn't in proper JSON format. For example, if the plain text of the response was Internal Server Error, which isn't JSON. Here's an example:
(async () => {
const response = await fetch('data:,Internal%20Server%20Error');
console.log('got response');
try {
await response.json();
} catch(e) {
console.log('error:', e.message);
}
})();
Does the code within flashResponseToUser(res) also need to be wrapped within a try-catch block since I am using res.json()?
If you wanted to be perfectly safe, yes. But, in most situations, it's easiest just to catch in one place, where you can handle the error. Instead of handling possible errors at every step of the process, you might handle the error just once, in the consumer, eg:
const getInfo = async () => {
const res = await fetch('/createurl', {
method: 'POST',
body: 'testData',
headers: {
'Content-Type': 'application/json'
}
})
if (!res.ok) {
throw new Error(res.status);
}
return res.json();
};
getInfo()
.then(flashResponseToUser)
.catch(() => {
alert('A server or network error occurred during the request!')
})
(assuming that flashResponseToUser will never throw, if provided with an expected object. If flashResponseToUser might throw anyway, you can separate out the .catches to distinguish network errors from other runtime errors)

JS Fetch - cannot get data from BadRequest response [duplicate]

This question already has answers here:
fetch: Reject promise with JSON error object
(5 answers)
Closed 3 years ago.
I am using React + Redux on the client side and I have the backend in NET CORE.
Client gets data from API using:
return fetch(`api/login`, requestOptions)
.then(response => {
if(!response.ok) {
return Promise.reject(response.json() as Promise<AuthError>);
} else {
return response.json() as Promise<ILoginResponse>
}
})
requstOptions are:
const requestOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
};
When the password is wrong, the server returns
404 Bad request
and the body is:
{"errorCode":2,"description":"Invalid Password"}
I would like to read the body but with this code, it is not possible because this response.json() as Promise<AuthError> produces an empty object.
Is there a way how to read the body of a bad request response?
As per the Fetch Documentation:
"The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing."
What you can also check is the Response object documentation. In there, you can check if the Response ok is set to false (so, in a then clause check the response.ok) and from that point on you can check the Response.text property. Check also the Response Documentation
Have you tried using catch and then inspecting error object?
...
.then(response => response.json())
.then(response => console.log('Success:', JSON.stringify(response)))
.catch(error => console.dir(error));

Categories

Resources