$w("#html).onMessage stack messages/runs multiple times in loop

Hey,
I have a loop that runs through all items and sends the address of the item to a html, in the html I use google geocoding to get the lat/lng and send it data back to the pagecode.
my code:

for (let item of res.items) {
        let address = item.address.formatted.replaceAll(" ", "+");
        $w("#html1").postMessage({ address: address });

        await new Promise((resolve) => {

            $w("#html1").onMessage(async (event) => {

                console.log("received message");

                item.lat = event.data.lat;
                item.lng = event.data.lng;

                await wixData.update(database, item);

                resolve();
            });
        });
    }

But the console.log(“received message”) stacks with the loop, that means: in the first loop I get one console.log(), in the second loop I get two console.log(), …

I know this problem from javascript, if you use .addEventListener(“message”) multiple times, but it shouldn’t appear in a .onMessage.
Is there any solution in Velo to remove the event, or do you have an idea, how I can change the code?

Because if I’d use this code, I always get undefined back:

async function runLoop() { //get the items
        for (let item of res.items) {
            let address = item.address.formatted.replaceAll(" ", "+");
            $w("#html1").postMessage({ address: address });
            await new Promise((resolve) => {
                let msg = HTMLonMessage();
                console.log(msg); //update database
                resolve();
            });
        }
    }
    let HTMLonMessage = $w("#html1").onMessage((event) => {
        let lat = event.data.lat;
        let lng = event.data.lng;
        return [lat, lng];
    });

Finally I found a solution for this problem, I really don’t know why I did not think of this earlier.

Let me explain you how it works:
At first we create a global variable promiseResolve , then we create a new promise.
Because we resolve our promise in another function, we need to set the value of promiseResolve to resolve ( promiseResolve = resolve ; ).

Then we post the item and the database to our html (if you only work with one database, you don’t need to do this).

let promiseResolve;

export async function button1_click() {

    let databases = ["database1", "database2"];

    for (let database of databases) {

        await wixData.query(database)
            .limit(1000)
            .find()
            .then(async (res) => {

                for (let item of res.items) {

                    await new Promise((resolve) => {

                        promiseResolve = resolve;

                        $w("#html1").postMessage({ obj: item, db: database });
                    });
                }
            });
    }
}

In our second function, we set the onMessage of the html:

export async function html1_message(event) {

    if (event.data.geocoding !== undefined) {

        let database = event.data.db;
        let item = event.data.item;

        await wixData.update(database, item);

        promiseResolve();
    }
}

After we updated our item, we resolve the promise (promiseResolve();).
Then the loop for (let item of res.items) {… goes on and updates the next item.

Hope this helps, if you have any questions, you can ask me.

please notice, that this code doesn’t work if you use

for (let i; i < something.length; i++) {
    //your code
}

or

res.items.forEach((item, index) => {
     //your code
});

because this both types of loops can’t handle async functions, so they’ll just
loop through without waiting for the resolve of your promise.