Async/await problem

Hi,
I still have some issue’s with async/await. i looked around alot and i thought i understood, but seems like something goes wrong. here is a piece of code that i am testing with.

export async function button14_click(event) {
    console.log("Before the repeater starts",1)
 let sizeDatabase
 await $w("#repeater1").forEachItem(async ($w,itemData,index)=>{
        console.log("in the repeater",2)
 await setTimeout(async function(){ 
 await console.log("in timeout function", 3)
 const breedte = await changeSizeToDatabaseSearchValue($w("#txtBreedte").value, $w("#ddBreedteAfSpan").value)
 const hoogte = await changeSizeToDatabaseSearchValue($w("#txtHoogte").value , $w("#ddHoogteDagAf").value)
    sizeDatabase =  await checkSize(breedte, hoogte)
            }, 1000);
 await console.log(sizeDatabase,4)
    })
 await console.log("na repeater",5)
}
//result
//1
//2
//5
//4
//3

i used the setTimeout to replace a query to the database, just to test. what i want is to do evrything in the right order.
I use changeSizeToDatabaseSearchValue to change the value of txtBreedte and txtHoogte, depending on a dropdown value and store it in breedte and hoogte. then i want to check if the changed values are good by using checkSize and i store them in sizeDatabase as a object {“breedte”: breedte, “hoogte” : hoogte")
after that i want to do something with those values stored in sizeDatabase, but whatever i do i keep getting undefined.

Any idea what i do wrong? kind regards
Kristof.

It’s not so clear what you’re trying to do here, but I can say you’re using too many “await”'s even in places they are completely unnecessary and it makes it difficult to read. so please get rid of the extra await’s + add semicolons.
Then post it again.

Oke, so i have a repeater with multiple elements in it.
i have a button that adds extra repeater items.
and i have u button that sends the data from the repeater elements to a database.

export function btnOffert_click(event) {
 let data = [{}]
     $w("#repeater1").forEachItem(($w,itemData,index)=>{
         data.push(addRolluik(index, 1, "Rolluikblad", $w("#txtBreedte").value +" * " +$w("#txtHoogte").value +" mm", $w("#txtBreedte").value, $w("#txtHoogte").value, "40", $w("#ddBreedteAfSpan").value, $w("#ddHoogteDagAf").value, "OffertesTest"))
         data.push(addOnderdeel(index, 2, "Type lamel", $w("#rbTypeLamel").value, "OffertesTest"))
         data.push(addOnderdeel(index, 3, "Bladkleur", $w("#rbKleurBlad").value, "OffertesTest"))
         data.push(addOnderdeel(index, 2, "Onderlat kleur", $w("#rbKleurKast").value, "OffertesTest"))
    })
//this should only excecute when the repeater is done.
    sendDataToDatabase(a)
}

the sendDataToDatabase function will loop trough “data” to send it to the database.

the function addOnderdeel() and addRolluik() is to ge the data from the repeater, and convert it to an object.
those functions also are getting data a database like a price, a size of something, discription, etc. so they have a small delay.

when i press the button “btnOffert_click” the “sendDataToDatabase()” function will start before i got my data pushed while it should only start after after all the data is pushed to “data”

hpe this clears things out

Kind regards
Kristof.

Hey Kristof, sorry, but I gotta say that I’m a bit confused with your code. If you are looking to add to a repeater and/or modify some of its entries, then maybe these two examples will help:

Input Components in Repeater
Use input components in a repeater, and apply inline and global actions to repeater content.

To-Do List
Let users create, filter, and update their own customized to-do list. The same functionality can be created using data binding or with the Wix Data API.

Hi Yisrael.
adding or modifying the repeater isn’t the issue,
the only thing i need is to know how i run some code when repeater.forEach is done, if my repeater.forEach isn’t done yet and it sends “data” to the database then i won’t get all the data the user inputed.

I guess the problem could be in calling the function addRolluik and addOnderdeel. Show us that code so we can help you further. But, as a wild guess, try :

export async function btnOffert_click(event) {
 let data = [{}]
     $w("#repeater1").forEachItem(($w,itemData,index)=>{
         data.push(await addRolluik(index, 1, "Rolluikblad", $w("#txtBreedte").value +" * " +$w("#txtHoogte").value +" mm", $w("#txtBreedte").value, $w("#txtHoogte").value, "40", $w("#ddBreedteAfSpan").value, $w("#ddHoogteDagAf").value, "OffertesTest"))

(watch the async and await). And make the called function async too.But, again, it is better to show us that code.

Hello Giri Zana,

addRolluik is just a functionthat puts evrything in an abject.


function addRolluik(indexNr, sortNr, naam, info, breedte = 0, hoogte = 0, korting,breedteSpan,hoogteAf, db) {
 var ref = $w("#txtReferentie").value
 if (ref === "") {
        ref = bestelNr
    }
 let toInsert = {
 "bestelNr": bestelNr,
 "referentie": ref,
 "indexNr": indexNr,
 "sortNr": sortNr,
 "naam": naam,
 "info": info,
 "breedte": Number(breedte),
 "hoogte": Number(hoogte),
 "breedteSpan" : breedteSpan,
 "hoogteAf" : hoogteAf,
 "korting": korting,
    }
 return toInsert
}

asames goe’s for addnderdeel


function addOnderdeel(indexNr, sortNr, naam, info, db) {
 if (naam === "Positie") {

 if (info === "") {
            info = "R" + (pad(indexNr + 1)).toString()
        } else {}
    } else if (naam === "Uitvoering blad") {
 if (info === "") {
            info = "1/2 Open (Standaard)"
        }
    }
 let toInsert = {
 "bestelNr": bestelNr,
 "referentie": $w("#txtReferentie").value,
 "indexNr": indexNr,
 "sortNr": sortNr,
 "naam": naam,
 "info": info
    }
 return toInsert
}

It returns this object and pushes it to “data”
atm i don’t use any query’s to a database yet thats why in my first post here i used an settimeout function to imitate an query (since it can take a few ms to get the result)

The code i wrote actualy does work if there is no delay, but when there is a delay the variable data is empty.

About the code you gave


export async function btnOffert_click(event) {
 let data = [{}]
     $w("#repeater1").forEachItem(($w,itemData,index)=>{
         data.push(await addRolluik(index, 1, "Rolluikblad", $w("#txtBreedte").value +" * " +$w("#txtHoogte").value +" mm", $w("#txtBreedte").value, $w("#txtHoogte").value, "40", $w("#ddBreedteAfSpan").value, $w("#ddHoogteDagAf").value, "OffertesTest"))

async in the button function won’t work in the forEachItem.
i have to put async before the callback function from the forEachItem.
but if i do that, do i also need to do async in the button function?



export async function btnOffert_click(event) {
 let data = [{}]
     await $w("#repeater1").forEachItem(async($w,itemData,index)=>{
         data.push(await addRolluik(index, 1, "Rolluikblad", $w("#txtBreedte").value +" * " +$w("#txtHoogte").value +" mm", $w("#txtBreedte").value, $w("#txtHoogte").value, "40", $w("#ddBreedteAfSpan").value, $w("#ddHoogteDagAf").value, "OffertesTest"))

like this? added a await infront of the repeater, added an async before the callback

kind regards
Kristof.

To make evrything more clear.
this is what my code does at the moment.


//a normal function returning a value. (no delay by getting value from a database.)
function one(a,b){
 const ab = a+b
 return ab
}
//a function with a 200ms delay(to imitate a database request)
function two (){
 //looks up data in database (takes up 0.2 sec)
 $w("#repeater1").forEachItem(($item,itemData,index)=>{
 setTimeout(async function(){ 
 const a = await "Some databaseValue"
 return a
        }, 200)
    }
 
}
//function to get data from both functions.
async function getData(){
 const res1 = one(1,2)
 const res2 = await two()

 const result =  await Promise.all([res1,res2])
 return result
}
//logging the result
async function log(){
 const a = await getData()
 console.log(a)
}
//start the Logg function
log()

// result:
//[3,undefined]
//
// what i need
//[3,"Some databaseValue"]

setTimeout is an imitation of a database request.
but i keep getting undefined when having a delay somewhere