1

I am using Vue with typescript, and I am using firebase firestore to get data

I have a asynchronous function, which returns a promise, which I resolve with .then, but inside the function, when I try to get the arrays length it gives me 0, while when I console.log the actual array, it gives me the full array

getAllProducts(this.productType, this.gender).then(productList =>{
    console.log(productList)
    console.log(productList.length)
    productList.forEach((product)=>{
        for(const [key, value] of Object.entries(product)){
            console.log(key, value)
        }
    })
})

Get product function

async getAllProducts(productType: string, gender: string): Promise<product[]>{
    const allProducts = [] as product[]

    const productDatabase = db.firestore().collection(['products', productType, gender].join('/'));

    const snapshot = await productDatabase.get().catch(()=>{console.log("Error in getting all products");})
    if(!snapshot){
        return allProducts
        //EDIT HERE FOR FRONTEND ERROR MESSAGE
    }

    snapshot.forEach(async product=>{
        const nowProduct = product.data() as product;

        nowProduct.id = product.id
        nowProduct.productType = productType
        nowProduct.imageURL = await this.getImageURL(product.id, productType)

        const [tFrameColour, tLensColour] = await this.getFrameColours()
        nowProduct.frameColours = nowProduct.frameColours.map(value=>tFrameColour[value])
        nowProduct.lensColours = nowProduct.lensColours.map(value=>tLensColour[value])

        allProducts.push(nowProduct)
    })

    // FINAL RETURN
    return allProducts
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Lucien950
  • 195
  • 2
  • 10
  • `async` does not work in `forEach`. Use the traditional `for` loop instead. – Terry Dec 30 '20 at 17:43
  • How to iterate through snapshot without forEach? https://firebase.google.com/docs/firestore/query-data/get-data#get_multiple_documents_from_a_collection – Lucien950 Dec 30 '20 at 17:59

1 Answers1

2

The problem here is that forEach resolves always resolves as void, no matter if you have async promises running within.

So, your code will run the return statement before executing the statements within the forEach

You should do like this instead:

return Promise.all(
  snapshot.docs.map(async product=> {
    const nowProduct = product.data() as product;

    nowProduct.id = product.id
    nowProduct.productType = productType
    nowProduct.imageURL = await this.getImageURL(product.id, productType)

    const [tFrameColour, tLensColour] = await this.getFrameColours()
    nowProduct.frameColours = nowProduct.frameColours.map(value=>tFrameColour[value])
    nowProduct.lensColours = nowProduct.lensColours.map(value=>tLensColour[value])

    return nowProduct
  })
)

This way you don't even need the allProducts array being initialized before

Felipe Malara
  • 1,796
  • 1
  • 7
  • 13