catch not running javascript - javascript

I have an async await function that handles form submission in React Native:
const handleSubmit = async () => {
const credentials = { email, password }
try {
login(credentials)
} catch {
console.error('ERROR')
//external function to reset form
resetForm()
return
}
// User authenticated, go to home screen
await goToHomeScreen()
}
Where login(), which makes the API call, is
const login = (credentials) => {
axios
.post(`${MY_API}/login`, credentials)
.then((res) => {
console.log(res.data)
})
.catch(() => {
throw 'Error'
})
}
The idea is that if the authentication call fails, my login() throws an error, which should run the return in my handleSubmit's catch {}, ending the function. However, the catch never runs, and goToHomeScreen() runs. What am I doing wrong?

not just return but do something
axios
.get(url)
.then((response) => {
console.log('response', response);
}
.catch((error) => {
console.log('CATCH');
window.alert('CATCH');
}

Try this, it is working for me
const login = (credentials) => {
axios
.post(`${MY_API}/login`, credentials)
.then((res) => {
console.log(res.data)
})
.catch((error ) => {
return Promise.reject(error);
})
}

since you are using async-await, you can call login as:
const handleSubmit = async () => {
const credentials = { email, password }
try {
await login(credentials)
} catch {
console.error('ERROR')
//external function to reset form
resetForm()
return
}
// User authenticated, go to home screen
await goToHomeScreen()
}
const login = async (credentials) => {
return await axios.post(`${MY_API}/login`, credentials);
}
it will solve the issue

Related

Function does not return true even if it goes through

I can't seem to make this work but I want to return true every-time the function executes successfully, which in this case is "Changing the password".
async function ChangePassword(data) {
const auth = getAuth();
let res = false;
const credential = EmailAuthProvider.credential(
auth.currentUser.email,
data.oldPassword
);
reauthenticateWithCredential(auth.currentUser, credential)
.then(() => {
updatePassword(auth.currentUser, data.password)
.then(() => {
toast.success("Password changed successfully");
res = true;
console.log("res ",res);
})
.catch((error) => {
toast.error(error.message);
});
})
.catch((error) => {
toast.error(error.message);
});
return res;
}
The res variable when called by other functions always results in false even though I see the toast message "Password changed successfully".
async function changePassword() {
if (password === "" || confirmPassword === "" || oldPassword === "") {
toast.error("Please fill all the fields");
} else if (password !== confirmPassword) {
toast.error("Passwords do not match");
} else {
let data = { oldPassword, password };
await ChangePassword(data).then((res) => {
if (res === true) {
setChangePasswordModal(false);
setOpen(false);
}
});
}
}
The if condition in above code never executes because res is always false. I know it has something to do with async await but can't figure out how to make it work
async function ChangePassword(data) {
const auth = getAuth();
let res = false;
const credential = EmailAuthProvider.credential(
auth.currentUser.email,
data.oldPassword
);
reauthenticateWithCredential(auth.currentUser, credential)
.then(() => {
updatePassword(auth.currentUser, data.password)
.then(() => {
toast.success("Password changed successfully");
res = true;
console.log("res ",res);
})
.catch((error) => {
toast.error(error.message);
});
})
.catch((error) => {
toast.error(error.message);
});
return res;
}
Has many logical errors in it.
First you should decide whether you're going to use async and its feature await or classical Promise .thenable -style. Please do not use both, it will only confuse you and the reader.
Let's ditch the async (since you don't even use await), and Promises are chainable, you do not (and MUST not) nest .then blocks, use this instead:
function ChangePassword(data) {
const auth = getAuth();
const credential = EmailAuthProvider.credential(auth.currentUser.email, data.oldPassword);
return reauthenticateWithCredential(auth.currentUser, credential)
.then(() => {
return updatePassword(auth.currentUser, data.password)
})
.then(() => {
toast.success("Password changed successfully");
return true;
})
.catch((error) => {
toast.error(error.message);
return false;
})
}
The key here is that ChangePassword itself returns a Promise.*
The caller is then responsible to call it with .then or use async in combination with await:
ChangePassword({/* data */}).then((result) => {
console.log("ChangePassword done", result)
})
The same code looks a lot cleaner if you use async:
async function ChangePassword(data) {
const auth = getAuth();
const credential = EmailAuthProvider.credential(auth.currentUser.email, data.oldPassword);
try {
await reauthenticateWithCredential(auth.currentUser, credential);
await updatePassword(auth.currentUser, data.password);
toast.success("Password changed successfully");
return true;
} catch (error) {
toast.error(error.message);
return false;
}
}
(If you were wondering how that would look like).
*a function tagged as async ALWAYS returns a promise, by the way.

React-native AsyncStorage Issue

In the code snippet you see, I am trying to reach the data that I have determined through asyncStorage in the getToken and `` functions, but when I open the page with these codes from the emulator, the data is empty for the first time, and then when I do ctrl+s from the editor, the data is full. What is the reason for this problem?
App.js Page
getToken: async () => {
const token = AsyncStorage.getItem('userToken');
return token;
},
getMail: async () => {
const mail = AsyncStorage.getItem('userMail');
return mail;
},
OrderListScreen Page
getToken().then((res) => {
if(res){
setToken(res);
console.log(token)
}else {
setToken('');
}
});
getMail().then((res) => {
if(res){
setMail(res);
console.log(mail)
}else {
setMail('');
}
});
Apply await before using AsyncStorage.getItem:
getToken: async () => {
const token = await AsyncStorage.getItem('userToken');
return token;
},
getMail: async () => {
const mail = await AsyncStorage.getItem('userMail');
return mail;
},
In the log you'll not get the updated state in next line of state setter.
getToken().then((res) => {
if(res){
setToken(res);
console.log(token); //You'll never get this value here because state updates are asynchronous in React
console.log("res : ", res);
}else {
setToken('');
}
});
getMail().then((res) => {
if(res){
setMail(res);
console.log(mail)//You'll never get this value here because state updates are asynchronous in React
console.log("Email Res : ", res);
}else {
setMail('');
}
});

How can I "encapsulate" this code into a module so it could become reusable?

I have got this Node.JS snippet and would like to write it as a module, so I can use recaptcha in different parts of my system.
This is how it currently looks like:
app.post('/register_user', (req, res) => {
const secret_key = process.env.RECAPTCHA_SECRET;
const token = req.body.recaptcha;
const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secret_key}&response=${token}`;
fetch(url, { method: "post",})
.then((response) => response.json())
.then((google_response) => {
if (google_response.success == true) {
res.format({'text/html': () => res.redirect(303, '/register'),})
} else {
return res.send({ response: "Failed" });
}
})
.catch((error) => {
return res.json({ error });
});
})
I have tried to write the following module which works absolutely great, but I have absolute no idea about how to call it from the app.post, since I always get undefined as return:
import fetch from 'node-fetch';
export function fetch_out(url, timeout = 7000) {
return Promise.race([
fetch(url),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('timeout')), timeout)
)
]);
}
export async function checkRecaptcha(token, secret_key){
const url = "https://www.google.com/recaptcha/api/siteverify?secret=" + secret_key + "&response=" + token;
try{
const response = await fetch_out(url, 1000);
const google_response = await response.json();
}catch(error){
return error;
}
return google_response;
}
Any help would be appreciated! Thanks!
You could make this method reusable by removing the framework actions that need to happen and only return if the validation was successful or not. This way, it will be reusable in another project that doesn't use a specific framework.
Example module;
export async function checkRecaptcha(token, secret_key) {
const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secret_key}&response=${token}`;
const response = await fetch(url, { method: "post",});
if (!response.ok) return false;
const json = await response.json();
if (!json.success) return false;
return true;
}
Usage:
import { checkRecaptcha } from "./some-file-name";
app.post('/register_user', async (req, res) => {
const isHuman = await checkRecaptcha(req.body.recaptcha, process.env.RECAPTCHA_SECRET);
if (!isHuman) {
return res.send({ response: "Failed" });
}
return res.format({'text/html': () => res.redirect(303, '/register'),});
});
If you specifically want to call an action after the validation, you can also use successful and error callbacks.

Handle promises inside redux actions with thunk

I have a fake login function like this
const login = (email, password) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (email === "demo#gmail.com" && password === "demo1234") {
resolve(200);
} else {
reject(401);
}
}, 1000);
});
};
This is my authAction.js file
export const login = (email,password) => async(dispatch) => {
try {
await fakeLogin(email,password)
dispatch({
type:LOGIN,
payload:{}
})
} catch (error) {
console.log(error)
}
}
In my LoginPage.js react component I call the action like this
const submit = ({ email, password }) => {
props.login(email, password).then((e) => console.log("then",e)).catch(err=>console.log("ca"));
};
If I pass the wrong credentials it logs the error code 401 inside the action. But in the LoginPage component, it always comes to the then block and prints undefined.
Even if I pass the right credentials it comes to then block and prints 'undefined'
But If I modify the action to return 200 or the error
export const login = (email,password) => async(dispatch) => {
try {
await fakeLogin(email,password)
dispatch({
type:LOGIN,
payload:{}
})
return 200
} catch (error) {
return error;
}
}
Now it prints the error code in "then" block of the LoginPage component.
Simply I want to inform the LoginPage component of what happened to the request. So what I am doing right now is okay or is there any other performance optimal way to do this?
Any help
Thanks in advance!
You forgot return value in then and throw error in catch
export const login = (email,password) => async(dispatch) => {
try {
const res = await fakeLogin(email,password)
dispatch({
type:LOGIN,
payload:{}
})
return res
} catch (error) {
console.log(error)
throw error
}
}

react.js: Create resource with redux-form, rest api and async/await

I'm trying to create new resource with redux form and REST api.
I dispatch createPost action and I want to check if the post was succeeded before continue.
const handleFormSubmit = (values, dispatch) => {
dispatch(createPost(values));
//I want to check here if post was succeeded.
//if status = 200 this.props.history.push('/');
}
export function createPost(values) {
return async function(dispatch) {
let request;
try {
request = await axios.post(`${ROOT_URL}/posts`, values)
} catch(err) {
request = { err };
}
dispatch({
type: CREATE_POST,
payload: request
})
}
}
Return a promise, something like this :
export function createPost(values) {
return function(dispatch) {
return new Promise( async function(resolve, reject){
let request;
try {
request = await axios.post(`${ROOT_URL}/posts`, values)
} catch(err) {
reject(err)
}
dispatch({
type: CREATE_POST,
payload: request
})
resolve(request)
})
}
}
const handleFormSubmit = () => {
dispatch(createPost(values))
.then( res => {
// do yoour stuff on succes
} )
.catch(err => {
// stuff on err
})
}
As seeing your codes, I don't think you need to use promise.
Please try like following:
const getAction = (values) => (dispatch) => {
return axios
.post(`${ROOT_URL}/posts`, values)
.then(
() => {
dispatch({
type: CREATE_POST,
payload: request
})
},
() => {
throw new SubmissionError({
_error: 'Failed'
});
}
);
};
const handleSubmit = (values) => {
return dispatch(getAction(values));
};

Categories