Calling api request after Complete other requests - javascript

beforeTabSwitch: async (tab) => {
let flag = false;
if (tab === 'PAYMENT') {
if (this.isManualValidated) {
flag = true;
this.savePayment().then((response) => {
this.placeOrder();
});
}
}
return flag;
}
savePayment: async function () {
this.$http.post(this.savePaymentRoute)
.then(response => {
await this.getOrderSummary();
})
.catch(error => {
});
},
placeOrder: async function () {
this.$http.post(this.saveOrderRoute)
.then(response => {
})
.catch(error => {
console.log('placeOrder | ' + error);
})
},
When Place Order Button Clicked beforeTabSwitch() which validate data & then call savePayment() . as savePayment request is complete then call getOrderSummary() then call placeOrder() request.
Call in Order: savePayment() > getOrderSummary() > placeOrder()
but the issue is after execute savePayment() immediately placeOrder() execution start after complete then getOrderSummary() execute which is wrong.
i already try with Promises, callback but same issue.

You need to start writing some clean code. And you should either use promises approach or async-await approach. I hope this code help you:
beforeTabSwitch: async (tab) => {
if (tab !== 'PAYMENT') {
return false;
}
if (!this.isManualValidated) {
return false;
}
try {
const response = await this.savePayment();
this.placeOrder();
} catch (error) {
console.log(error);
}
return true;
},
savePayment: async function () {
try {
const paymentResponse = await this.$http.post(this.savePaymentRoute);
const summaryResponse = await this.getOrderSummary();
} catch (error) {
console.log(error);
}
},
placeOrder: async function () {
try {
const response = await this.$http.post(this.saveOrderRoute);
} catch (error) {
console.log('placeOrder | ' + error);
}
},

Related

How to wait for all promises to resolve

I have two api call.
I want to do some calculation based on the results of both api.
I am using Promise.all() for waiting for both promises to resolve.
const getHashTagList = async () => {
loader.start();
try {
await getAllHashTags().then((response: any) => {
setHashtagList([...response?.data]);
});
} catch (err) {
} finally {
loader.stop();
}
};
const getUserFollowingHT = async () => {
loader.start();
try {
await getUserDetails().then((response: any) => {
setUserFollowingHT([...response?.data?.followingHashtags]);
});
} catch (err) {
} finally {
loader.stop();
}
};
For calling these 2 promises I am using below syntax:
useEffect(() => {
//getHashTagList();
// getUserFollowingHT();
Promise.all([getHashTagList, getUserFollowingHT]).then(
(combineResp) => {
console.log(combineResp);
}
);
}, []);
But in the output I am getting function declaration syntax.
It is not able to get call those promises.
Try this
useEffect(() => {
(async () => {
const values = await Promise.all([getHashTagList, getUserFollowingHT]);
console.log(values);
})();
}, []);

Why is this asynchronous function being called twice

I am trying to create a user with email and password using firebase, but when I call the function that creates it, it is called twice and I get an error because I am trying to register the email that is already in use.
I noticed that the console.log('CALLED') is called once, I don't understand why RegisterWithEmail is called twice. My auth flow only creates the userDocument in the confirmation phase, for this reason userSnap.length equals zero in the second call and tries to create again.
How can I call this function once?
FILE: emailconfirm.page.tsx
registerEmail = async data => {
const { setRegStatus, createDoc } = this.props;
console.log('CALLED')
await RegisterWithEmail(data).then(res => {
console.log('Final response ', res)
if(res === 'EMAIL_VERIFIED') {
createDoc()
setRegStatus({ status: 'created', data: res })
}
else if(res === 'SOMETHING_WENT_WRONG'){
setRegStatus({ status: 'error', data: res })
}
}).catch(err => {
console.log('Error ', err)
setRegStatus({ status: 'error', data: err })
})
}
FILE: firebase.utils.tsx
export const RegisterWithEmail = async user => {
console.log("Called Once...");
if(!user) return 'SOMETHING_WENT_WRONG';
else {
const snap = await firestore.collection('users').where('email', '==', user.email).get();
const docs = snap.docs.map((doc) => doc.data());
if (docs.length !== 0) return 'EMAIL_HAS_ALREADY_BEEN_TAKEN';
try {
console.log("Trying to register email...");
return await auth.createUserWithEmailAndPassword(user.email, user.password).then(async usr => {
await usr.user.updateProfile({
displayName: user.name
}) // SETTING NAME
const sendVerifyEmail = usr.user.sendEmailVerification().then(() => setTimer(usr.user, 5))
return await sendVerifyEmail.then(msg => {
console.log('Finishing...', msg)
if(msg.txt !== 'waiting') {
if(msg.error) {
throw msg.txt
}
else return msg.txt
}
}).catch(() => {
throw 'EMAIL_NOT_SENT'
})
}).catch(() => {
throw 'USER_NOT_CREATED'
})
} catch (err) {
throw 'USER_ALREADY_REGISTERED'
}
}
}
Developer console:
You shouldn't be mixing and matching .then()s in async functions for your own sanity's sake.
Something like
export const RegisterWithEmail = async (user) => {
if (!user) return false;
const snap = await firestore.collection("users").where("email", "==", user.email).get();
const docs = snap.docs.map((doc) => doc.data());
if (docs.length !== 0) return false;
console.log("Trying to register email...");
try {
const resp = await auth.createUserWithEmailAndPassword(user.email, user.password);
// then ...
return true;
} catch (err) {
// catch ...
}
};
might work better for you.
I need more code to be sure, but I think you should add await
registerEmail = async data => {
console.log('CALLED')
await RegisterWithEmail(data)
}

how to return value from a promise function

I have a function which checks whether a device is online or not. Below is the code.
const ping = require('ping');
export function findDevices(device) {
try {
const hosts = [device];
let result = null;
hosts.forEach((host) => {
ping.promise.probe(host)
.then((res) => {
console.log(res.alive)
result = res.alive;
return {
Status: result
}
});
});
} catch (err) {
logger.error(err, '[ config - findDevices() ]');
console.error(err);
return {
Status: "Failed"
}
}
}
I am calling this function in a redux action like this:
export function start(device) {
return dispatch => {
const status = Connectionstatus.findDevices(device);
return dispatch({
type: actionTypes.CONNECTIONSTATUS,
payload: {
ConnectionStatus: status
}
})
};
}
I am expective the status variable to be either true or false. But i am getting as undefined even though i am returning the value inside then of the promise function. i have tried awaiting this call and still its not working. Any help would be much appreciated. Thanks.
If that's the case you can do like this
const getStatus = async () => {
try {
const hosts = [device];
const promises = [];
hosts.forEach((host) => {
promises.push(ping.promise.probe(host));
});
const result = await Promise.all(promises);
const status = result.map((r) => { return r.alive; });
return status;
} catch (err) {
logger.error(err, '[ config - findDevices() ]');
return { status: 'Failed' };
}
};
Not 100% sure what all the vars are, but have you considered using async/await to simplify things a bit like this?
const getStatus122 = async device => {
return await Promise.all([device].map(ping.promise.probe))
.then(({ alive }) => alive)
.then(Status => ({ Status }))
.catch(error => {
logger.error(error, '[ config - findDevices() ]');
return { Status: 'Failed' };
})
}
More on that here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
With Promises you should inspect the promised result either in when or catch callback functions. With async/await the code may look a bit simpler. Here is the version with explicit promises.
const ping = require('ping');
const Connectionstatus = {
findDevices: (device) => {
return ping.promise.probe(device).then((res) => {
const result = res.alive;
console.log(result);
return {
Status: result,
};
}).catch((err) => {
logger.error(err, '[ config - findDevices() ]');
console.error(err);
return {
Status: "failed"
}
});
}
}
export function start(device) {
return dispatch => {
Connectionstatus.
findDevices(device).
then((status) => {
dispatch({
type: actionTypes.CONNECTIONSTATUS,
payload: {
ConnectionStatus: status
}
})
});
};
}
You may see that error handling moved to the catch callback function while the dispatch is done in the then callback function. And this is the answer to your question.

Dispatch async action

By changing my action to async I am not able to dispatch it. Whenever I make the dispatch it enters the cath with the value false. Here is my page where I dispatch the action from mounted hook (I tried created too)
mounted () {
this.$store.dispatch('productById', this.$route.params['id']).then((response) => {
this.product = response
})
.catch(err => {
console.log(err)
})
}
And this is my action
async productById ({commit}, payload) {
const AuthStr = await getAdminOrRespondentAuth()
return new Promise((resolve, reject) => {
commit(PRODUCT_BY_ID)
axios.get(`${API_BASE}/products/${payload}`, {
params: {
origin: '1'
},
transformRequest: [function (data, headers) {
delete headers.common.Authorization
headers.Authorization = AuthStr
return data
}],
paramsSerializer: params => parseParams(params)
}).then(response => {
if (response.status === 200) {
commit(PRODUCT_BY_ID_SUCCESS, response.data)
resolve(response.data)
} else {
reject(response)
}
})
.catch(err => {
if (err.response.data.idStatus === 1) {
commit(PRODUCT_BY_ID_SUCCESS, err.response.data.data)
reject(err)
}
})
})
}
When the Vue enters mounted hook it "dispatch the action" and goes straight into the catch block not calling my action. My action is not executed.
If I change my action to sync, everything works normally. I need this action to be async because getAdminOrRespondentAuth function thats call oidc async method to recover user.
What I'm doing wrong?
#Samurai8 is right. Thanks for the help. My getAdminOrRespondentAuth was not returning a promise correctly. After correcting the error of the function everything came back to work. This is the function that generate error discribed:
async function getAdminOrRespondentAuth () {
let mgr = new Mgr()
var adminToken = await mgr.getToken()
if (adminToken !== false) {
return 'Bearer '.concat(adminToken)
} else {
let usrToken = localStorage.getItem('user-token')
return 'Bearer '.concat(usrToken)
}
}
Here is the function that works:
async function getAdminOrRespondentAuth () {
var adminToken = ''
return new Promise(async (resolve, reject) => {
let mgr = new Mgr()
try {
adminToken = await mgr.getToken()
} catch (error) {
adminToken = error
}
if (adminToken !== false) {
resolve('Bearer '.concat(adminToken))
} else {
let usrToken = localStorage.getItem('user-token')
if (usrToken !== null) {
resolve('Bearer '.concat(usrToken))
} else {
resolve('')
}
}
})
}

async await with promises is then block required

How to basically async await properly? I have created a helper for AsyncStorage which async awaits automatically but do the users of this also have to use async await or promise approach to get the value?
This code works but unable to use the syntax correctly.
here is my code:
class AsyncStorageHelper {
static getItem = async (key: string) => {
let value: any = "";
try {
value = await AsyncStorage.getItem(key);
} catch (error) {
console.log(`Error item: ${value}`);
throw new Error(`Error ${value}`);
}
return value;
};
}
AsyncStorageHelper.getItem("logins")
.then(result => {
if (result) {
if (result === "1") {
navigate(SCREEN1);
} else {
navigate(SCREEN2);
}
}
})
.catch(err => {
navigate(LOGINSCREEN);
});
How can I convert the AsyncStorageHelper code to async await as depending on the result I want to navigate to different places.
await must be used inside a async function.
async function helper() {
try {
const result = await AsyncStorageHelper.getItem("logins");
if (result) {
if (result === "1") {
navigate(SCREEN1);
} else {
navigate(SCREEN2);
}
}
} catch (error) {
navigate(LOGINSCREEN);
}
}
helper()
Async functions and promise-returning function can be used externally in the same manner.
AsyncStorageHelper.getItem("logins")
.then(result => {
if (result) {
if (result === "1") {
navigate(SCREEN1);
} else {
navigate(SCREEN2);
}
}
})
.catch(err => {
navigate(LOGINSCREEN);
});
Is the same as:
// note: this code must run in another async function
// so we can use the keyword await
try {
const result = await AsyncStorageHelper.getItem("logins");
if (result) {
if (result === "1") {
navigate(SCREEN1);
} else {
navigate(SCREEN2);
}
}
} catch (err) {
navigate(LOGINSCREEN);
}
Note: your code has an unknown code path. What happens when AsyncStorageHelper.getItem("logins") returns a falsy value? You essentially have a noop and this might not be the desired behavior.
class AsyncStorageHelper {
static async getItem(key : string) {
let value: any = ""
try {
value = await AsyncStorage.getItem(key)
} catch (error) {
console.log(`Error item: ${value}`)
throw new Error(`Error ${value}`)
}
return value
}
}
try {
const result = await AsyncStorageHelper.getItem("logins")
if (result)
(result === "1") ? navigate(SCREEN1): navigate(SCREEN2)
} catch(err) {
navigate(LOGINSCREEN)
}

Categories

Resources