Variable not incrementing as expected

My code:

export function function() {

 let queryOptions = {
 "suppressAuth": true, // Setting this option to true will bypass the permissions.
 };

 var itemsQueried = 0
 var itemsProcessed = 0;
 var itemsAmended = 0;
 var itemsArray = [];

 wixData.query('Notifications')
 .ascending("_updatedDate")
 .limit(1000)
 .find(queryOptions)
 .then(data => {
            itemsQueried = data.items.length;
            console.log("query result " + itemsQueried + " items");
            data.items.forEach(function (item) {

                itemsProcessed++;

 var id = item._id;
 var endpoint = item.title;
 var latitude = item.latitude;
 var longitude = item.longitude;
 var range = item.range;
 var email = item.email;
 var initialNearbyHotspots = item.initialNearbyHotspots;
 var usedCurrentLocation = item.usedCurrentLocation;

                itemsArray.push(id);

                getJSON(endpoint)
 .then(json => json.data.length)
 .then(length => {
 if (length > initialNearbyHotspots) {

                            itemsAmended++;

 var toUpdate = {
 "_id": id,
 "title": endpoint,
 "latitude": latitude,
 "longitude": longitude,
 "range": range,
 "email": email,
 "initialNearbyHotspots": length,
 "usedCurrentLocation": usedCurrentLocation
 };

 let updateOptions = {
 "suppressAuth": true, // Setting this option to true will bypass the permissions.
 };

                            wixData.update('Notifications', toUpdate, updateOptions)
 .then(updatedItem => {
                                    console.log(id + " completed " + initialNearbyHotspots + " to " + length);
                                    sendEmail(updatedItem._id, latitude, longitude);
 })
 .catch(error => console.error(error))

 } else {

 var toUpdate = {
 "_id": id,
 "title": endpoint,
 "latitude": latitude,
 "longitude": longitude,
 "range": range,
 "email": email,
 "initialNearbyHotspots": initialNearbyHotspots,
 "usedCurrentLocation": usedCurrentLocation
 };

 let updateOptions = {
 "suppressAuth": true, // Setting this option to true will bypass the permissions.
 };

                            wixData.update('Notifications', toUpdate, updateOptions)
 .then(updatedItem => {
                                    console.log(id + "completed")
 })
 .catch(error => console.error(error))
 }
 })
 .catch(error => console.error(error))
 })
 })
 .finally(() => {
            console.log("processed " + itemsProcessed + " items");
            console.log("amended " + itemsAmended + " items");
            console.log(itemsArray);
 })
}

The itemsProcessed variable is incrementing as expected, however the itemsAmended variable is always returning 0 in console.log, irrespective of how many times the if (length > initialNearbyHotspots) condition is resolved as TRUE and should therefore be executing itemsAmended++

I would appreciate any pointers (and general advice as to optimisation, I find .then promises a bit unintuitive) - thanks in advance!

See the following for more information about Promises:

Very difficult to read the code as it is not very well formatted, so I copied into an IDE to get a better look. Some questions, observations, and comments:

  • You have a data.items.forEach() loop that checks how many results?

  • In this loop, you are calling asynchronous functions with Promises that don’t get resolved before calling these functions again (as far as I can tell).

  • What is getJSON() ? Are you sure it’s executing and actually returning something?

  • Are you sure that the ( length > initialNearbyHotspots ) condition is resolved as TRUE? Try putting a console.log() right after it to see if the execution of the code even gets there and to see what’s happening.

  • If you get a lot of items returned from your query, you might end up with a very heavy loop.

There’s more, but to be honest, your code isn’t exactly simple, and it’s not too clear what it is you’re trying to accomplish.

Some of the Promise issues might be solved by using async/await instead of .then() .

Let’s see what we can do.

Hi @yisrael-wix , thanks for the reply and for your pointers. Sorry, not sure what I could do about the formatting, I’ve lifted my nice code from the IDE into the code block to post but it’s ended up like that!

You have a data.items.forEach() loop that checks how many results? Currently less than 10.

What is getJSON()? Are you sure it’s executing and actually returning something? Yes, this is returning JSON from an API endpoint as expected.

Are you sure that the ( length > initialNearbyHotspots ) condition is resolved as TRUE? Try putting a console.log() right after it to see if the execution of the code even gets there and to see what’s happening. The code block following the if condition resolved as TRUE is definitely executing when the condition is met, as I am seeing console . log ( id + " completed " + initialNearbyHotspots + " to " + length ); in my Site Events for those items where length > initialNearbyHotspots.

To double-check, putting console.log(itemsAmended) in the if block, it is showing an incrementing integer. Would this indicate that the issue is with when itemsAmended is being called in the finally block?

About my code overall, function() is being executed by the job scheduler once per hour. My aim is for it go through each item in the Alerts collection and check an API endpoint for each item to update the initialNearbyHotspots property with the length of the array at the respective endpoint, if it is bigger (this is the if block in question) I am using wixData.update to update the initialNearbyHotspots property of that item.

In the other case ( else ), I am performing wixData.update with the existing property values (i.e. those returned by the query) so that the last updated property changes for these items, too, without actually changing anything else about the item. This is in case of my Alerts collection containing >1,000 items, in which case I want the 1,000 items which haven’t been subjected to this code for the longest period to be returned in WixData.query - I hope that makes sense?

I will have a play around with my code to see if I can implement async/await in order to fix any problems, and try an alternative to forEach (I’ve just read that forEach doesn’t wait for Promises, which is a problem!) I think I could split up the function itself into smaller sub-functions, too :grinning:

P.S. your Promises, Promises link returns a 404 :wink:

Link to Promises, Promises fixed. :beers:

@yisrael-wix thank you. I’ve rebuilt my code using async/await and have split up my function into various logical sub-functions. The behaviour of my code is mostly as expected*, but I’m unsure how to implement an incremented variable in order to capture (by way of the console) how many times the if condition is resolved as true - where does this code need to sit?

*one thing I’m confused by is that console.log(“completed”) is executed early on, before the forEach loop has finished - why is this?

Thanks as always for any input.

export async function processAlerts() {
 let queryResult = await queryItems();
 await forEachItem(queryResult);
    console.log("completed");
}

export async function queryItems() {
 try {

 const queryOptions = {
 "suppressAuth": true,
 };

 const results = await wixData.query("Alerts")
 .ascending("_updatedDate")
 .limit(1000)
 .eq("status", "active")
 .find(queryOptions);
        console.log(results);
 return results.items;
 
 } catch (error) {
        console.error(error)
 return error;
 }
}

export async function forEachItem(arr) {
 await arr.forEach(function (item) {
            getJSONAtEndpoint(item);
 })
}

export async function getJSONAtEndpoint(item) {
 try {
 let oldN = item.hotspotsInRange;
 let endpoint = item.endpoint;
 let json = await getJSON(endpoint);
 let newN = json.data.length;
 if (newN > oldN) 
            updateItemNewN(item, newN);
 } else {
            updateItemOldN(item);
 }
 } catch (error) {
        console.error(error)
 }
}

export async function updateItemNewN(item, newN) {
 let toUpdate = {
 "_id": item._id,
 "endpoint": item.endpoint,
 "lat": item.lat,
 "lon": item.lon,
 "range": item.range,
 "email": item.email,
 "firstName": item.firstName,
 "lastName": item.lastName,
 "hotspotsInRange": newN, //update hotspotsInRange with the value retrieved from getJSON
 "usedCurrentLocation": item.usedCurrentLocation,
 "contactId": item.contactId,
 "status": "active"
 };

 const options = {
 "suppressAuth": true,
 };

 let updatedItem = await wixData.update('Alerts', toUpdate, options);
    sendAlertEmail(updatedItem.contactId, updatedItem._id, updatedItem.lat,        updatedItem.lon, updatedItem.firstName);

}

export async function updateItemOldN(item) {
 let toUpdate = {
 "_id": item._id,
 "endpoint": item.endpoint,
 "lat": item.lat,
 "lon": item.lon,
 "range": item.range,
 "email": item.email,
 "firstName": item.firstName,
 "lastName": item.lastName,
 "hotspotsInRange": item.hotspotsInRange, //update hotspotsInRange with existing value
 "usedCurrentLocation": item.usedCurrentLocation,
 "contactId": item.contactId,
 "status": "active"
 };

 const options = {
 "suppressAuth": true,
 };

 await wixData.update('Alerts', toUpdate, options);

}