Why catch invoked with success promise? - javascript

I have maybe weird things happen I send a request to an Endpoint "/Login" and it's given me the response well!
and I do my stuff, but for some reason, I see a warning that says,
Unhandled Promise Rejection / typeError: undefined is not an object
(evaluating 'error.response.data')
If anybody has an explanation for it?
Code snippet
signIn = data => {
this.setState({loading: true});
API.post('/login', data)
.then(response => {
let {
data: {
data: {
response: {token},
},
},
} = response;
this.setState({loading: false});
reactotron.log('response', response);
reactotron.log(token);
deviceStorage.saveKey('id_token', token);
})
.catch(error => {
alert('catched!!'); // it's appear :)
this.setState({error: error.response.data, loading: false});
reactotron.error(error.response.data);
});
};
=
The wrong was here in this function ~_~ !
why get me an error?
_deviceStorage.default.saveKey is not a function
import { AsyncStorage } from '#react-native-community/async-storage';
import reactotron from 'reactotron-react-native';
const deviceStorage = {
// our AsyncStorage functions will go here :)
saveItem= async(key, value)=>{
try {
await AsyncStorage.setItem(key, value);
} catch (error) {
reactotron.log('AsyncStorage Error: ' + error.message);
}
}
};
export default deviceStorage;

error is a string representation of the error message( rejection message). But you are treating it as if it's an object when you say error.response.data
.catch(error => {
alert('catched!!'); // it's appear :)
this.setState({error: error, loading: false});
reactotron.error(error.response.data);
});

The catch could be invoked if an error is encountered in the then block. Check your then block for any possible errors. That might be the reason why catch is invoked even when the promise returned success.
const promise1 = new Promise(function(resolve, reject) {
resolve("resp");
});
promise1.then(function(resp) {
console.log(resp);
throw 'error'
}).catch(function(error) {
console.error(error);
});

Related

Javascript uncaugh error in promise even with a catch

With Javascript, I am trying to make a call to an external API when a form is submited.
I am using promises in order to set follow up actions once the call is done and to catch eventual errors.
This is where my problem is, even if I think I am catching my errors correctly, the console throws an
Uncaught (in promise) error : [The error I throw]
I do not understand why.
Here is a minimal version of my code which would reproduce the error when the refreshToken is expired :
try {
functionGeneratingTheError();
} catch (error) {
doSomethingElse();
}
function functionGeneratingTheError() {
var getTokenCallPayload = {
"client_id" : clientId,
"client_secret" : clientSecret,
"refresh_token" : refreshToken,
"grant_type" : "refresh_token"
};
var getTokenCallOptions = {
"method" : "POST",
"body" : JSON.stringify(getTokenCallPayload),
"muteHttpExceptions" : false
};
fetch(tokenURL, getTokenCallOptions)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error("Error");
}
})
.then(data => {
doSomething();
})
.then(response=> {
doSomethingAgain();
})
.catch(error => {
throw error;
});
}
If I understand correctly, when the fetch is a bad request, it should throw the error "Error" which should then be caught in the first catch and run the doSomethingElse() function.
However, instead of doing that, I get this error in the browser console "Uncaught (in promise) Error: Error"
What am I doing wrong ?
I have tried including the fetch in a try{}catch(){} but it doesn't change anything.
I also tried not throwing the error and directly call my doSomethingElse() function, but then the following .then fails because data is undefined.
Change your functionGeneratingTheError function to return the chained promise like below:
function functionGeneratingTheError() {
var getTokenCallPayload = {
"client_id" : clientId,
"client_secret" : clientSecret,
"refresh_token" : refreshToken,
"grant_type" : "refresh_token"
};
var getTokenCallOptions = {
"method" : "POST",
"body" : JSON.stringify(getTokenCallPayload),
"muteHttpExceptions" : false
};
return
fetch(tokenURL, getTokenCallOptions)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error("Error");
}
})
.then(data => {
doSomething();
})
.then(response=> {
doSomethingAgain();
})
.catch(error => {
throw error;
});
}
And then await it in your calling code by wrapping the calling code inside an async self invoking function like so:
(async function() {
try {
await functionGeneratingTheError();
} catch (error) {
doSomethingElse();
}
})();
You can read more about async/await here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

How to use a conditional validation after Axios call in Vue app

I have a Vue application where I make a POST request to my backend. I am now trying to call a validation method after the response from my backend returned back an error to my frontend. But for some reason my code is not executed:
UPDATED QUESTION CODE:
validateFormInput(){
this.$refs.form.validate()
},
saveSelectionVoter() {
var pageURL = window.location.href;
var lastURLSegment = pageURL.substr(pageURL.lastIndexOf('/') + 1);
this.votersSelectArray.voterAvailableTimes = [...this.votersSelectArray.voterAvailableTimes, ...this.selected]
console.log(JSON.stringify( this.votersSelectArray))
axios.post("http://localhost:8080/api/votercontroller/",
this.votersSelectArray,
{
params: {
meetingName: lastURLSegment,
}
},
).then(function(response){
})
.catch(function (error){
this.validateFormInput()
console.log(error)
})
this.selected = []
},
This causes a new error:
TypeError: Cannot read property 'validateFormInput' of undefined
always have a catch to see the error return
axios return you a promise so it captures the error if there is any
axios.post('url')
.then((res) => {
// do somthing
}).catch(err){
console.log(err)
}
You can either use the callback method to catch the response/error or use the Promise way, which is my favorite because of scope and readability.
You start by declaring your function with async
async saveSelectionVoter() {
Then you use a try/catch block to handle the response/error:
try{
const response = await axios.post(url, params)
// handle response here
} catch (error) {
// handle error here
}

There is a way to return an error inside catch without throw a new one?

I have a custom error that I call inside try. And I want to return this error inside catch without throw a new one.
const callSomething = async () => {
try {
doSomething();
} catch (error) {
// This function receive the error with the additional properties, so we need the custom error object
customErrorTreatment(error);
}
};
This function is where the error is first call.
const doSomething = async () => {
try {
// This function throw a custom error class with additional properties
throwApiError({
responseMessage: 'Some error occour',
responseStatus: 500,
});
} catch (error) {
// If I return error, the function callSomething just receive the value without error.
return error;
// I can call throwApiError again, but feels ugly, that is the only way?
return throwApiError({
responseMessage: error.responseMessage
responseStatus: error.status,
});
}
};
This is the custom error class and function
export const ApiError = class ApiError extends Error {
constructor({ responseMessage, responseStatus, error }) {
super(error);
this.responseMessage = responseMessage;
this.responseStatus = responseStatus;
}
};
const throwApiError = ({ responseMessage, responseStatus, error }) => {
throw new ApiError({ responseMessage, responseStatus});
};
Don't call throwApiError() again. Just throw error if you want the promise to stay rejected - that's how promises work.
Or get rid of your catch() handler entirely so the error just propagates naturally back up to a higher level without your intervention. You don't appear to be doing anything in the catch handler so perhaps you can just remove it.
In short No, because to generate an error you need to throw, and your method is a common method for error handling. but there is another way to manage errors like this:
const callSomething = async () => {
let { result, error } = resdoSomething();
if (error) {
return throwApiError({
responseMessage: error.responseMessage
responseStatus: error.status,
});
}
console.log(result)
// do somethings
};
and
const doSomething = async () => {
try {
let result = myfunction()
return {result: result , error : null}
} catch (error) {
return {result : null, error: error};
}
};
In this way you can reduce the number of try/catch

this await throwing unexpected token error

I have a simple async function. It just sends a request and returns the data:
export const updatePanorama = async ({ commit }, payload) => {
const urlEnd = '/v1/pano/update'
const type = 'post'
const resp = await api.asyncRequest(urlEnd, type, payload)
commit('SET_PANORAMA', resp.data)
return resp
}
And this is how I'm using the function:
handleUpdatePanorama (panorama) {
const payload = {}
this.updatePanorama(payload).then(resp => {
this.setIsLoading(false)
this.handleAlert('updateSuccess', 'success')
}).catch(() => {
this.setIsLoading(false)
this.handleAlert('updateError', 'danger')
})
},
The problem is, the code after catch runs if there's an error inside then. But this way I don't know whether the catch error is an request error or and error triggered by the code inside then.
I'm trying try and catch to solve that problem:
handleUpdatePanorama (panorama) {
try {
const payload = {}
const resp = await this.updatePanorama(payload)
console.log('resp:', resp)
this.setIsLoading(false)
this.handleAlert('updateSuccess', 'success')
} catch (err) {
this.setIsLoading(false)
this.handleAlert('updateError', 'danger')
})
},
However, I get an unexpected token error in this line: await this.updatePanorama(payload)
What am I doing wrong?
The problem is, the code after catch runs if there's an error inside then
The solution for that is to not use catch, but the second then parameter. Have a look at the difference between .then(…).catch(…) and .then(…, …) for details.
I'm trying try and catch to solve that problem
That won't work, the catch clause will still be called if there's an exception thrown by setIsLoading or handleAlert.
I get an unexpected token error. What am I doing wrong?
You have not declared the handleUpdatePanorama method as async.
To mitigate the issues and fix the syntax, you could write
async handleUpdatePanorama (panorama) {
var result
try {
const payload = {}
const resp = await this.updatePanorama(payload)
console.log('resp:', resp)
result = ['updateSuccess', 'success']
} catch (err) {
result = ['updateError', 'danger']
} finally {
this.setIsLoading(false)
}
this.handleAlert(...result)
},
If you need to handle errors specifically from updatePanorama, use the second argument to .then(onSuccess, onError)
handleUpdatePanorama(panorama) {
const payload = {}
this.updatePanorama(payload).then(resp => {
this.setIsLoading(false)
this.handleAlert('updateSuccess', 'success')
}, err => {
// handle error from updatePanorama
// you can throw err if you also want to handle the error in .catch()
}).catch(() => {
this.setIsLoading(false)
this.handleAlert('updateError', 'danger')
})
}
note: if you return (or have no return statement) from the error handler, any subsequent .then(onSuccess will execute, if you throw an error (or return Promise.reject() for example, then the .catch() code will also run

How can I solve this error occurring in Reactjs and Firebase Google Cloud Firestore?

I am trying to fetch data from Firebase Cloud Firestore and load it into my Reactjs app upon loading into the browser. However, I get the following error.
error message
Unhandled Rejection (TypeError): Cannot read property 'then' of undefined
The error occurs at the following line:
firebaseService.getUserData(authUser.uid).then(user => { ...
I get an initial page load followed by about a two second delay and then the error pops up. So I suspect it's coming from some missing promise or callback not being handled correctly. I have tried using async await in several places without success.
How can I solve this problem to fetch and load my data correctly?
Auth.js
import firebaseService from 'firebaseService';
...
class Auth extends Component {
...
firebaseCheck = () => {
firebaseService.onAuthStateChanged(authUser => {
if (authUser) {
this.props.showMessage({ message: 'Logging in with Firebase' });
// Retrieve user data from Firebase
firebaseService.getUserData(authUser.uid).then(user => { // <-- error occurs here
this.props.setUserDataFirebase(user, authUser);
this.props.showMessage({ message: 'Logged in with Firebase' });
})
}
});
};
}
firebaseService.js
getUserData = userId => {
if (!firebase.apps.length) {
return;
}
const docRef = this.firestore.doc('users/myuserid');
docRef.get().then(doc => {
if (doc.exists) {
console.log("Document data:", doc.data());
return doc.data;
} else {
console.log("No such document!");
}
}).catch(error => {
console.log("Error getting document:", error);
});
};
When you call the getUserData function, you need to return a Promise before the function ends. When you call docRef.get, I'm assuming that is an asynchronous call, so while that is happening, the function ends and returns undefined. By the time it gets to return doc.data, it's too late.
getUserData = userId =>
new Promise((resolve, reject) => {
if (!firebase.apps.length) {
reject();
}
docRef.get().then(doc => {
if (doc.exists) {
console.log("Document data:", doc.data());
resolve(doc.data);
} else {
console.log("No such document!");
reject();
}
}).catch(error => {
console.log("Error getting document:", error);
reject();
});
});

Categories

Resources