Ad

Inside A Promise I Want To Assign Value(the Value Itself Comes From Some Another Promise ) To A Variable Which Will Be Used Outside Of That Promise

In my Firestore DB, I have two collections books and categories. In categories collection all documents have only one field i.e. name, and in books collection the document contains multiple field and one of them is type which is an array of datatype DocumentRef, which means each document in books can have multiple values of categories-name.

Now, for each document in the books collection, I want to get all the values of associated categories name in a single string.

This is what I have till now.

database
    .collection("books")
    .get()
    .then(snapshot => {
        snapshot.forEach(doc => {
            renderTypes(doc);
        });
    });

/** The renderTypes function **/
renderTypes = doc => {
    let typeArrayRef = doc.data().type; // assigning the array of documentRefs

    console.log("total elements in types array is ", typeArrayRef.length);
    promiseVar = new Promise((resolve, reject) => {
        typeList = " ";
        // looping through each items inside the array
        typeArrayRef.forEach(type => {
            type.get().then(res => {
                typeList = typeList + " " + res.data().name;
            });
            // unccommenting this line gives a mixed output (out of order)
            // console.log(`String containing all the types are ${ type }`);
        });
        resolve(type); // resolving with type string
    });

    promiseVar.then(type => {
        console.log("Inside the then of promiseVar", type);
    });
};

Now the output I get is :

total elements in types array is 6 
total elements in types array is 3
total elements in types array is 1 

Inside the then of promiseVar
Inside the then of promiseVar 
Inside the then of promiseVar

Nothing is being printed in the last three lines but logging it inside the promiseVar gives the output but is mixed (i.e. there is no fixed order).

It seems like the promiseVar is resolving straightaway. Is there any way around this?

Ad

Answer

If you want to aggregate a list of async values, you can use Promise.all and then compute the result. In your case, it may look something like this:

renderTypes = doc => {
    const typeArrayRef = doc.data().type; // assigning the array of documentRefs
    console.log("total elements in types array is ", typeArrayRef.length);

    const promiseVar = Promise
      .all(typeArrayRef.map(type => type.get()))
      .then(types => {
        const typeList = types.map(type => type.data().name).join(' ');
        return typeList;
      });

    promiseVar.then(type => {
        console.log("Inside the then of promiseVar", type);
    });
};

First, we create a list of promises and wait for all of them to resolve. When it's ready, types is the list of all responses. Chaining .then makes promiseVar resolve the desired result. We can make it even simpler with await keyword:

renderTypes = async doc => {
    const typeArrayRef = doc.data().type; // assigning the array of documentRefs
    console.log("total elements in types array is ", typeArrayRef.length);

    const types = await Promise.all(typeArrayRef.map(type => type.get()));
    const typeList = types.map(type => type.data().name).join(' ');

    // Not really _inside_ now.
    console.log("Inside the then of promiseVar", typeList);
};
Ad
source: stackoverflow.com
Ad