How to push to an array within a query's forEach loop

Hi, I’m trying to return data from a query to the front end after adding and manipulating and putting the new info into another array. I’m not managing to return this array.

function ...(...) {
let foodAmounts = [];
let foodItemAmounts = {
type: "",
foodName: ""
}
wixData.query("Foodstuff")
.find()
.then((results) => {
if (results.items.length > 0) {
results.items.forEach((foodItem) => {
foodItemAmounts.foodName = foodItem.title;
switch (true) {
case (foodItem.foodGroup === "cereals"):
foodItemAmounts.type = "cereals";
break;
case (foodItem.foodGroup === "leafy vegetables"):
//removed code for brevity, the switch is ok
}
foodAmounts.push(foodItemAmounts);
console.log("foodAmounts[0].foodName after push" + foodAmounts[0].foodName); //this prints ok as I'd expect
})
}
})
.catch((err) => {
console.error(err);
});
console.log("foodAmounts[0].foodName before return " + foodAmounts[0].foodName ); //here the array is empty and I get undefined
return foodAmounts;
}

It seems like in the then clause the array push is happening successfully. But the array is afterwards returned empty.
I tried adding another .then and returning the array from there, but that didn’t do the trick. What am I missing? Is the a scope or a timing issue?

Try this

let foodQuery = await wixData.query("Foodstuff")...

And then run a loop from there

thank you @carlos-alvarez . I did try that, but it doesn’t parse, I got:

As the message says, you need to make the containing function async. Something like this:

async function ...(...) {

However I don’t think this is your problem…

The problem is that you are logging the array outside of the .then(), which means it actually ran before the code in the .then().

See the following articles for more information regarding Promises:

@yisrael-wix indeed, i was missing that, added it (in a few necessary places) and it now works. Thank you Yisrael and @carlos-alvarez for the answer and for the quick replies!

1 Like

It’s worth mentioning that this prints [object Object],[object Object],[object Object],[object Object]…
I’m not sure why. But the objects are accessable, so we’re good. Thanks!

@yisrael-wix @carlos-alvarez I’m afraid I celebrated too early. While I do have progress and see an object being pushed to the array, it’s always the same instance.
I do see it is iterating over the various 63 lines I’ve got, but the final array I get has the same object 63 times. Why would that be? I’m not sure whether this warrants a new thread. Will give you guys a chance to answer here first.

@experimentnoxx Where are you inspecting the array? Did you change any code from your original post?

This line prints the same item each time through the loop since it uses the index 0.

console.log("foodAmounts[0].foodName after push" + foodAmounts[0].foodName); //this prints ok as I'd expect

If you want to print the new line each time you’ll have to increment the index each time you push another entry.

Does this help?

@yisrael-wix I’m inspecting it in several places.
Note: When I originally posted the question, I got the prints from the backend in the editor preview. Now it stopped doing that and I’m only getting frontend logs there. Very odd. Also, I’m not seeing printouts from the prints of the complete structures (such as console.log(result) at all, not even in the Site Events Monitor. Looks like something broke on your end.

I return the array to the frontend. It has 63 parts as the forEach iterated over 63 lines. That’s good. But when I open it up in the editor console I see that all 63 have the same content.
Additional comments about inspections are in the code below

export async function functionImCallingFromFrontend(whatever) {
// removed irrelevant code
let foodItemsAmounts = await calculateAllFoodsAmounts(typesAmounts, calorieTarget);
var nutritionPlan = {
typesAmounts: typesAmounts,
calorieTarget: calorieTarget,
foodItemsAmounts: foodItemsAmounts //I print this out in frontend
};
return nutritionPlan;
}


async function calculateAllFoodsAmounts(typesAmounts, calorieTarget) {
let foodAmounts = [];
let foodItemAmounts = {
type: "",
//removed some lines for brevity
_id: ""
}
let foodQuery = await wixData.query("Foodstuff")
.limit(500)
.find()
.then((results) => {
if (results.items.length > 0) {
let internalFoodAmounts = [];
results.items.forEach((foodItem) => {
foodItemAmounts.foodName = foodItem.title;
foodItemAmounts.foodType = foodItem.foodGroup;
foodItemAmounts._id = foodItem._id;
switch (true) {
case (foodItem.foodGroup === "cereals"):
foodItemAmounts.type = "cereals";
break;
case (foodItem.foodGroup === "leafy vegetables"):
// removed most cases
break;
}
foodAmounts.push(foodItemAmounts);
console.log(foodAmounts);//this and results aren't printing    // anything  now. Earlier today this did print out all the //instances built from the query, as I expected
console.log(foodItemAmounts); //this prints to site monitor, I //see all the instances i expect
console.log(results);
})
}
return foodAmounts;
})
.catch((err) => {
console.error(err);
});
return foodQuery; //returning foodquery or foodAmounts here    // gives the same results
}

//Front-end code:
$w.onReady(function () {
// stuff
calculatePlan(familySize, amountWeeks, parsedFamilyData).then(result => {
console.log(result);

1 Like

Never mind, solved that too.
the let foodItemAmounts statement needed to be in foreach statement and not before it.