Synchronized in typescript angular 5 - javascript

I have the following code.
public async getOrderInforAsync(customerOrderId) {
return new Promise((resolve, reject) => {
this.orderEntryService.getCommissionIncentives(customerOrderId)
.subscribe(
response => {
Object.assign(this.order, response);
this.order.bookingDate = this.order.bookingDate ? new Date(this.order.bookingDate) : null;
this.order.estBillDate = this.order.estBillDate ? new Date(this.order.estBillDate) : null;
this.order.orderSplit.forEach(element => {
element.rcNumberFullName = `${this.order.customerOrderRCNumber}${element.rcNumberSuffix}`;
});
this.initialQuantityAllocated();
this.orderSummary.allocatedEstCommissionPercent = this.calculateTotalOrderPercent();
this.orderSummary.allocatedEstCommissionAmount = this.calculateTotalOrderAmount();
this.highlight = this.checkOrderSummary(this.orderSummary.allocatedEstCommissionPercent, this.orderSummary.allocatedEstCommissionAmount);
this.calculateAllocatedActualPercent();
this.calculateAllocatedActualAmount();
this.onChangeEstSalesPrice();
resolve();
},
error => {
reject();
}
);
});
}
Sometimes the resolve() is called before this.calculateAllocatedActualPercent() and this.calculateAllocatedActualAmount() are done.
So how to make this code run synchronized, it means all functions on this block code had done before resolve() called?

Try this :
public async getOrderInforAsync(customerOrderId) {
return new Promise((resolve, reject) => {
this.orderEntryService.getCommissionIncentives(customerOrderId)
.subscribe(
response => {
Object.assign(this.order, response);
this.order.bookingDate = this.order.bookingDate ? new Date(this.order.bookingDate) : null;
this.order.estBillDate = this.order.estBillDate ? new Date(this.order.estBillDate) : null;
this.order.orderSplit.forEach(element => {
element.rcNumberFullName = `${this.order.customerOrderRCNumber}${element.rcNumberSuffix}`;
});
this.initialQuantityAllocated();
this.orderSummary.allocatedEstCommissionPercent = this.calculateTotalOrderPercent();
this.orderSummary.allocatedEstCommissionAmount = this.calculateTotalOrderAmount();
this.highlight = this.checkOrderSummary(this.orderSummary.allocatedEstCommissionPercent, this.orderSummary.allocatedEstCommissionAmount);
await this.calculateAllocatedActualPercent();
await this.calculateAllocatedActualAmount();
this.onChangeEstSalesPrice();
resolve();
},
error => {
reject();
}
);
});
}
async calculateAllocatedActualPercent(){
return new Promise(resolve,reject){
// call api
if (data)
resolve(data);
else
reject()
}
}
async calculateAllocatedActualAmount(){
return new Promise(resolve,reject){
// call api
if (data)
resolve(data);
else
reject()
}
}

An async function returns a Promise. And to declare a function as async, you need to have an await call inside it.
Change your observable returned from this.orderEntryService.getCommissionIncentives(customerOrderId) .toPromise() and then await it.
Try this:
public async getOrderInforAsync(customerOrderId) {
try {
const response = await this.orderEntryService
.getCommissionIncentives(customerOrderId).toPromise();
this.order = { ...response };
this.order.bookingDate = this.order.bookingDate ? new Date(this.order.bookingDate) : null;
this.order.estBillDate = this.order.estBillDate ? new Date(this.order.estBillDate) : null;
for (let i = 0; i < this.order.orderSplit; i++) {
const element = this.order.orderSplit[i];
element.rcNumberFullName = `${this.order.customerOrderRCNumber}${element.rcNumberSuffix}`
}
this.initialQuantityAllocated();
this.orderSummary.allocatedEstCommissionPercent = this.calculateTotalOrderPercent();
this.orderSummary.allocatedEstCommissionAmount = this.calculateTotalOrderAmount();
this.highlight = this.checkOrderSummary(this.orderSummary.allocatedEstCommissionPercent, this.orderSummary.allocatedEstCommissionAmount);
this.calculateAllocatedActualPercent();
this.calculateAllocatedActualAmount();
this.onChangeEstSalesPrice();
return response;
} catch (error) {
return error;
}
}

Related

Nodejs multiple axios get requests return a Primise

How to return a Promise from the multiple axios get requests?
I have below code.
async function main() {
const URL_1 = 'abc.com/get1/data1';
const result_1 = await getData(URL_1);
const URL_2 = 'abc.com/get2/data2';
const result_2 = await getData(URL_2);
}
async function getData(dataURI) {
let getURI = dataURI;
const config = {
headers: {
Authorization: `Bearer ${my-token-text}`,
},
};
var finalData = [];
// until we get the next URL keep sending the requests
while (getURI != null) {
try {
const getResult = await axios.get(getURI, config);
if (getResult.status === 200) {
const receivedData = getResult.data.value;
finalData.push(...receivedData);
// check if we have nextLink in the payload
if (Object.prototype.hasOwnProperty.call(getResult.data, 'nextLink')) {
getURI = getResult.data.nextLink;
} else {
getURI = null;
return finalData;
}
}
} catch (err) {
break;
}
}
return null;
}
What I am trying to achieve is:
async function main() {
const URL_1 = 'abc.com/get1/data1';
const result_1 = getData(URL_1);
promisesArray.push(result_1);
const URL_2 = 'abc.com/get2/data2';
const result_2 = getData(URL_2);
promisesArray.push(result_2);
await Promise.allSettled(promisesArray).then((results) => {
console.log('Promise All Done: ', results);
});
}
This why I can perform all the requests in parallel.
But when I update the function getData(dataURI) to return return new Promise then I get error for await axios.
async function getData(dataURI) {
return new Promise((resolve, reject) => {
// Same code as above
});
}
I get error:
SyntaxError: await is only valid in async function
As Promise is not async I cannot await in the Promise.
Have you tried:
return new Promise(async (resolve, reject) => {
// Same code as above
});

How do I await for subscribe to subscribe

I used the code below until I found out that the getConnectedUser() function takes longer than verifyUser(), so this.userUID is undefined:
this.layoutService.getConnectedUser().subscribe(
(data) => {
this.userSaml = data;
this.layoutService.connectedUser.matricule = this.userSaml.matricule;
this.layoutService.connectedUser.profil = this.userSaml.profil;
this.layoutService.connectedUser.uid = this.userSaml.uid;
this.layoutService.connectedUser.username = this.userSaml.username;
this.layoutService.connectedUser.city = this.userSaml.city;
console.log("dashboard this.layoutService.connectedUser", this.layoutService.connectedUser);
},
(err) => {
throw err;
}
);
this.userUID = this.layoutService.connectedUser.uid;
console.log("this.userUID", this.userUID);
this.adminService.verifyUser(this.userUID).subscribe(
(data) => {
this.userStatus = data[0].status;
this.userProfile = data[0].profil;
console.log("userProfile" + JSON.stringify(data[0].profil));
this.userExists = true;
},
(err) => {
this.userExists = false;
}
);
So, I wanted to make sure that the getConnectedUser subscribe is completed to call the second one, I changed my code and added the .add method just like that:
this.layoutService.getConnectedUser().subscribe(
(data) => {
this.userExistsRefog = true;
this.userSaml = data;
this.layoutService.connectedUser.matricule = this.userSaml.matricule;
this.layoutService.connectedUser.profil = this.userSaml.profil;
this.layoutService.connectedUser.uid = this.userSaml.uid;
this.layoutService.connectedUser.username = this.userSaml.username;
this.layoutService.connectedUser.city = this.userSaml.city;
console.log("home connectedUser", this.layoutService.connectedUser);
},
(err) => {
this.userExistsRefog = false;
throw err;
}
).add(() => {
this.userUID = this.layoutService.connectedUser.uid;
console.log("this.userUID", this.userUID);
this.adminService.verifyUser(this.userUID).subscribe(
(data) => {
this.userStatus = data[0].status;
this.userProfile = data[0].profil;
console.log("userProfile" + JSON.stringify(data[0].profil));
this.userExists = true;
},
(err) => {
this.userExists = false;
}
);
});
I want to learn how to use the Async/await way for this example and what is the best approach to adopt for similar functionality ? Thanks
mainly you have two ways.
1.write the method call verifyuser() inside the subscription of getconnecteduser() method.in that way you will never get a null value.
2.you can use promises instead of observable subscription. then use async/await to delay the execution of the method.
async userTasks() {
const usersDetails = await this.layoutService.getConnectedUser().toPromise();
this.layoutService.connectedUser.uid = usersDetails.uid;
this.adminService.verifyUser(this.userUID).subscribe(
(data) => {
this.userStatus = data[0].status;
this.userProfile = data[0].profil;
console.log("userProfile" + JSON.stringify(data[0].profil));
this.userExists = true;
},
(err) => {
this.userExists = false;
}
);
}

cancel multiple promises inside a promise on unmount?

hi i want to cancel promise on unmount since i received warning,
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
My code:
const makeCancelable = (promise: Promise<void>) => {
let hasCanceled_ = false;
const wrappedPromise = new Promise((resolve, reject) => {
promise.then(
(val) => (hasCanceled_ ? reject({ isCanceled: true }) : resolve(val)),
(error) => (hasCanceled_ ? reject({ isCanceled: true }) : reject(error))
);
});
return {
promise: wrappedPromise,
cancel() {
hasCanceled_ = true;
},
};
};
useEffect(() => {
const initialize = async () => {
const getImageFilesystemKey = (remoteUri: string) => {
const [_, fileName] = remoteUri.split('toolbox-talks/');
return `${cacheDirectory}${fileName}`;
};
const filesystemUri = getImageFilesystemKey(uri);
try {
// Use the cached image if it exists
const metadata = await getInfoAsync(filesystemUri);
if (metadata.exists) {
console.log('resolve 1');
setFileUri(filesystemUri);
} else {
const imageObject = await downloadAsync(uri, filesystemUri);
console.log('resolve 2');
setFileUri(imageObject.uri);
}
// otherwise download to cache
} catch (err) {
console.log('error 3');
setFileUri(uri);
}
};
const cancelable = makeCancelable(initialize());
cancelable.promise
.then(() => {
console.log('reslved');
})
.catch((e) => {
console.log('e ', e);
});
return () => {
cancelable.cancel();
};
}, []);
but i still get warning on fast press, help me please?
You're cancelling the promise, but you are not cancelling the axios call or any of the logic that happens after it inside initialize(). So while it is true that the console won't print resolved, setFileUri will be called regardless, which causes your problem.
A solution could look like this (untested):
const makeCancelable = (promise: Promise<void>) => {
let hasCanceled_ = false;
const wrappedPromise = new Promise((resolve, reject) => {
promise.then(
val => (hasCanceled_ ? reject({ isCanceled: true }) : resolve(val)),
error => (hasCanceled_ ? reject({ isCanceled: true }) : reject(error))
);
});
return {
promise: wrappedPromise,
cancel() {
hasCanceled_ = true;
}
};
};
const initialize = async () => {
const getImageFilesystemKey = (remoteUri: string) => {
const [_, fileName] = remoteUri.split("toolbox-talks/");
return `${cacheDirectory}${fileName}`;
};
const filesystemUri = getImageFilesystemKey(uri);
try {
// Use the cached image if it exists
const metadata = await getInfoAsync(filesystemUri);
if (metadata.exists) {
console.log("resolve 1");
return filesystemUri;
} else {
const imageObject = await downloadAsync(uri, filesystemUri);
console.log("resolve 2");
return imageObject.uri;
}
// otherwise download to cache
} catch (err) {
console.error("error 3", err);
return uri;
}
};
useEffect(() => {
const cancelable = makeCancelable(initialize());
cancelable.promise.then(
fileURI => {
console.log("resolved");
setFileUri(fileURI);
},
() => {
// Your logic is such that it's only possible to get here if the promise is cancelled
console.log("cancelled");
}
);
return () => {
cancelable.cancel();
};
}, []);
This ensures that you will only call setFileUri if the promise is not cancelled (I did not check the logic of makeCancelable).

check if user in group ActiveDirectory.js node.js

In c# I would write something like this:
bool HasRole(string userName, string[] groupNames)
{
var ad = new ActiveDirectory();
return groupsNames.Any(groupName => ad.IsUserInGroup(userName, groupName);
}
and then just
if (HasRole("UserName", new[] {"group1", "group2"}))
//do something
in javascript it looks like all things are doing asynchronously, I've read about promises and so on, and tried this:
const ActiveDirectory = require('activedirectory2');
const Promise = require('promise');
const globals = require('./globals');
const activeDirectory = new ActiveDirectory(globals.AdConfig);
hasRole(msg, ...groupNames) {
if (groupNames == null || groupNames == undefined || groupNames.length == 0)
return false;
let promises = [];
groupNames.forEach(groupName => {
let promise = new Promise((resolve, reject) => {
activeDirectory.isUserMemberOf(msg.envelope.user.name, groupName, function (err, isMember) {
if (err) {
reject(err)
}
resolve(isMember);
});
});
promises.push(promise);
});
//I don't clearly understand how I can return promise result only or promise with the right result
let hasRole = false;
promises.forEach(promise => promise.done(result => {
if (result)
hasRole = result;
}));
return hasRole;
So how can write something like:
if (hasRole(msg, 'group1', 'group2'))
//do something...
I suppose I should return promise but how I can do it if i need to check multiple groups?
UPDATE
I wrapped the forEach loop in promise:
return new Promise((resolve, reject) => {
promises.forEach(promise => promise.done(result => {
if (result)
return resolve(result);
}));
and then:
hasRole(msg, 'group1', 'group2').done(result => {
if (result)
//do...
});
May there is another way?
Found a solution. Promises.all is what i needed.
Result code:
hasRole(msg, ...groupNames) {
let promises = [];
groupNames = groupNames.filter(x => x.trim().length > 0);
if (groupNames == undefined || groupNames.length == 0)
{
promises.push(new Promise.resolve(false));
return Promise.all(promises);
}
groupNames.forEach(groupName => {
let promise = new Promise((resolve, reject) => {
activeDirectory.isUserMemberOf(msg.envelope.user.name, groupName, function (err, isMember) {
if (err) {
reject(err)
}
resolve(isMember);
});
});
promises.push(promise);
});
return Promise.all(promises);
}

Returning promise data to the calling function

let func1 = function() {
return new Promise((resolve,reject) => {
let someVal = 5;
if (condition) {
resolve(someVal);
}
else {
reject('error occured');
}
});
}
let callingFunction = function() {
func1().then((res) => {
console.log("result",res); /* want to return res to the callingFunction */
return res; /* doesn't work as it returns to the .then not to the callingFunction I guess. */
});
}
let finalData = callingFunction();
Is it feasible to send the result from .then block of promise to callingFunction so that I get result in finalData?
let callingFunction = function() {
return func1().then((res) => {
console.log("result",res)
return res
})
}
callingFunction().then((res) => {
let finalData = res
})
The thing is that promise is an asynchronous operation, hence let finalData = callingFunction(); evaluates to undefined. If you'd like to use promise's result in callingFunction(), just pass res as an argument to it like this:
let func1 = function() {
return new Promise((resolve,reject) => {
let someVal = 5;
if (condition) {
resolve(someVal);
}
else {
reject('error occured');
}
});
}
func1().then((res) => {
console.log("result",res); /* want to return res to the callingFunction */
callingFunction(res);
});

Categories

Resources