Hi All – Really struggling with async/sync coding. I’ve read a lot of online articles already, but struggling getting it to work. Can anyone take a look at the below code?
In my code, I am creating a repeater of user “applicants”. This works perfectly, no problem. However, to the repeater I also need to add the user’s rating, which isn’t directly stored in the database, it has to be calculated. So I have a separate function “renderRating” that returns the respective applicants overall rating. The issue is, the For loop that creates the repeater runs immediately to completion while the renderRating function is being ran. So, each respective repeater is created before the rating is available, thus not being included in my repeater.
I tried adding a simple async to the main function and an await before renderRating, but it says await is undefined. What is the proper way to get all this done?
Thanks!
async function setAcceptedApplicants(proj_sub_id) {
$w("#acceptedAppBox").expand();
wixData.query("Project_Applications")
.eq("proj_sub_id", proj_sub_id)
.eq("status", "Accepted")
.ne("orgCompleted", "Yes")
.find()
.then( (results) => {
let appItems = results;
if (appItems.length === 0) {
$w("#noAcceptedApps").expand();
$w("#acceptedAppRepeater").collapse();
} else {
$w("#noAcceptedApps").collapse();
$w("#acceptedAppRepeater").expand();
$w("#acceptedAppBox").expand();
for (let i = 0; i < appItems.length; i++) {
wixData.get("Member_Database", appItems[i]._owner)
.then( (results) => {
let applicantItem = results;
let rating = await renderRating(applicantItem._id)
acceptedAppsRepeaterData.push({
"_id": applicantItem._id,
"profile_picture": applicantItem.profilePicture,
"name": applicantItem.firstName + " " + applicantItem.lastName,
});
if (acceptedAppsRepeaterData.length === appItems.length) {
$w("#acceptedAppRepeater").onItemReady( ($w, itemData, index) => {
$w("#image1").src = itemData.profile_picture;
$w("#acceptedAppName").text = itemData.name;
$w("#acceptedRating").text = rating;
});
$w("#acceptedAppRepeater").data = acceptedAppsRepeaterData;
}
});
}
}
});
}
Hey David
I’m not exactly sure about the whole case you’ve got here, but the error async is undefined
occurs because you’ve got a little mistake here:
async function setAcceptedApplicants(proj_sub_id) {
// This function is async
...
wixData.get("Member_Database", appItems[i]._owner)
.then( /* add async here */ async (results) => {
// This function was not async
let applicantItem = results;
let rating = await renderRating(applicantItem._id)
...
Please check it out and tell me if it helps
So, it removed the error, but it still is not working. The loop & repeater just keep running before the renderRating can run. Any additional thoughts?
async function setAcceptedApplicants(proj_sub_id) {
$w("#acceptedAppBox").expand();
wixData.query("Project_Applications")
.eq("proj_sub_id", proj_sub_id)
.eq("status", "Accepted")
.ne("orgCompleted", "Yes")
.find()
.then( (results) => {
let appItems = results.items;
if (appItems.length === 0) {
$w("#noAcceptedApps").expand();
$w("#acceptedAppRepeater").collapse();
} else {
$w("#noAcceptedApps").collapse();
$w("#acceptedAppRepeater").expand();
$w("#acceptedAppBox").expand();
for (let i = 0; i < appItems.length; i++) {
wixData.get("Member_Database", appItems[i]._owner)
.then( async (results) => {
let applicantItem = results;
let rating = await renderRating(applicantItem._id);
acceptedAppsRepeaterData.push({
"_id": applicantItem._id,
"profile_picture": applicantItem.profilePicture,
"name": applicantItem.firstName + " " + applicantItem.lastName,
"rating": rating,
});
if (acceptedAppsRepeaterData.length === appItems.length) {
$w("#acceptedAppRepeater").onItemReady( ($w, itemData, index) => {
$w("#image1").src = itemData.profile_picture;
$w("#acceptedAppName").text = itemData.name;
$w("#acceptedRating").text = rating;
});
$w("#acceptedAppRepeater").data = acceptedAppsRepeaterData;
}
});
}
}
});
}
Ok – So we may have actually fixed the async issue, but my RenderRating function I think is wrong. It is not returning rating?
function renderRating(applicantId) {
wixData.query("Project_Applications")
.eq('_owner', applicantId)
.eq('orgCompleted', "Yes")
.find()
.then(res => {
if (res.length > 0) {
let reviews = res.items;
// compute the average rating
let stats = reviews.reduce((agg, item) => {
return {
sum: agg.sum+item.userRating,
count: agg.count+1
};
}, {sum: 0, count: 0});
console.log(stats);
let rating = (Math.round(stats.sum * 2 / stats.count) / 2);
return rating;
}
});
}
Hi David, you’re missing a return statement right before wixData.query in the rating function.
Hi David, as Tomer mentioned you’re missing return statement in your renderRating function
function renderRating(applicantId) {
return wixData.query("Project_Applications")
// add ^^^^ return statement here
...
Edit I think I figured it out after slamming my forehead into the keyboard for a couple more hours. Going to toy with it some more before I ask any more basic questions. Thank you both!