Home > Back-end >  Absolutely lost on how to use js async
Absolutely lost on how to use js async

Time:08-11

I am using Javascript for a project and this the first time I've used it so I am a bit lost on how to use ascyn function.

I have a firebase/firestore database and I am trying to get a document id from it. I believe below is a good starting point for my code.

for(var i = 0; i < len; i  ){
    console.log('saving ingredent:', arrayCopy[i].ingredent)
    console.log('ingredent id:', getIId(arrayCopy, i))
}

This snippet of code should log the names of the document based on a given array value. Moving forward the getIId is as follows

export async function getIId(arrayCopy, i){
    const cIngredent = arrayCopy[i].ingredent
    var iID

    const ingredientRef = collection(fsdb, 'ingredientInfo')

    const q = query(ingredientRef, where("ingredientName", "==", cIngredent))

    onSnapshot(q, (snapshot) => {
        const ingredientSnap = snapshot.docs
        if(ingredientSnap.length != 0){
            let ingredents = []
            console.log('idCheck onSnapshot 2',ingredientSnap[0].id)
            iID = ingredientSnap[0].id
            ingredents.push(iID)
            console.log('array: ', ingredents)
            return ingredents
        }else{
            console.log('theres no value')
            console.log('idCheck onSnapshot else 2',iID)
            return iID
        }
    })

    console.log('outside iiD: ', iID)
}

what ends up happening is that

ingredent id: underfined

Comes before the values of the ingredients

idCheck onSnapshot ###############
idCheck onSnapshot 2 ###############
array [###############]

Where ############### is the correct document id. I am not sure how to get the right value from onSnapshot and have it return to as the value from getIId. Once again the value before the return inside onSnapShot is correct.

CodePudding user response:

You need to return something from inside if your getIId function, there is no magic, if you want to use onSnapshot - then you need to wrap it in a Promise object and return this object with handling reject and resolve (and dont forget to unsubscribe from onSnapshot after that) but if you need to get a result only once - use getDocs.

Examples: https://firebase.google.com/docs/firestore/query-data/queries

So your code will look like

export async function getIId(arrayCopy, i) {
  const cIngredent = arrayCopy[i].ingredent;
  const ingredientRef = collection(fsdb, "ingredientInfo");

  const q = query(ingredientRef, where("ingredientName", "==", cIngredent));
  const getDocsResult = await getDocs(q);
  const result = getDocsResult.docs.map((x) => x.id);

  if (result.length === 0) {
    console.log("No items found");
    return undefined;
  } else {
    console.log("array: ", result);
    return result[0]; // we need only 1 item, right?
  }
}

also, the function that will use getIId will need to await for the result of this function. Or to use getIId(...).then(res => console.log(res));

export async function something(arrayCopy) {
  const len = arrayCopy.length;
  for (var i = 0; i < len; i  ) {
    console.log("saving ingredent:", arrayCopy[i].ingredent);
    console.log("ingredent id:", await getIId(arrayCopy, i));
  }
}

CodePudding user response:

Assuming that onSnapshot and associated callbacks are correct, you just need to add a return to the async function.

return iID

Then the for loop should loop like this in order to make sure everything prints in the right order

for(let i = 0; i < len; i  ){
    getIId(arrayCopy, i).then((id)=>{
         console.log('saving ingredent:', arrayCopy[i].ingredent)
         console.log('ingredent id:', id)
    }
    )
}
  • Related