skip to Main Content

The Problem is with the uplines.push.
I always get an empty uplines array so the last part of the code doesn’t run. The promises resolve later and I get the correct data. May I know how to go about doing it the correct way?

 const getAllUplines = async () => {
uplines = [];
const findUser = async (userFid) => {
  const userDoc = await firestore.collection("users").doc(userFid).get();
  if (userDoc.exists) {
    const user = { ...userDoc.data(), id: userDoc.id };
    console.log(user);
    uplines.push(user);
    if (user.immediateUplineFid) {
      findUser(user.immediateUplineFid); //self looping
    }
  } else {
    console.log("No User Found");
    return null;
  }
};

sale.rens.forEach(async (ren) => {
  findUser(ren.userFid);
});
console.log(uplines);
return uplines;


};



let uplines = await getAllUplines();
  console.log(uplines);

  uplines = uplines.filter(
    (v, i) => uplines.findIndex((index) => index === v) === i
  ); //remove duplicates

  uplines.forEach((user) => {
    if (user.chatId) {
      sendTelegramMessage(user.chatId, saleToDisplay, currentUser.displayName);
      console.log("Telegram Message Sent to " + user.displayName);
    } else {
      console.log(user.displayName + " has no chatId");
    }
  });

2

Answers


  1. There are a few things that you have missed out while implementing the async call, which are explained in the inline comments in the code snippet.

    A short explanation for what happened in your code is that in the line sale.rens.forEach you are passing an async function in the argument, which does not make any difference to the function forEach, it will execute it without waiting for it to complete.

    Therefore in my answer I am using Promise.all to wait for all the async function calls to complete before returning the result.

    // This is wrapped in an immediately executed async function because await in root is not supported here
    (async () => {
      const mockGetData = () => new Promise(resolve => setTimeout(resolve, 1000));
      const sale = {
        rens: [
          { userFid: 1 },
          { userFid: 2 },
          { userFid: 3 }
        ]
      };
      
      const getAllUplines = async () => {
        const uplines = [];
        const findUser = async (userFid) => {
          // Simulating an async function call
          const userDoc = await mockGetData();
          console.log("User data received");
          uplines.push(`User ${userFid}`);
        };
    
        const promises = [];
        sale.rens.forEach(ren => {  // This function in foreach does not have to be declared as async
          // The function findUser is an async function, which returns a promise, so we have to keep track of all the promises returned to be used later
          promises.push(findUser(ren.userFid));
        });
        await Promise.all(promises);
        return uplines;
      };
    
      let uplines = await getAllUplines();
      console.log(uplines);
    })();
    Login or Signup to reply.
  2. In order to get the results of getAllUplines() properly, you need to add await to all async functions called in getAllUplines().

    const getAllUplines = async () => {
        uplines = [];
        const findUser = async (userFid) => {
            const userDoc = await firestore.collection("users").doc(userFid).get();
            if (userDoc.exists) {
                const user = { ...userDoc.data(), id: userDoc.id };
                console.log(user);
                uplines.push(user);
                if (user.immediateUplineFid) {
                    await findUser(user.immediateUplineFid); //self looping
                }
            } else {
                console.log("No User Found");
                return null;
            }
        };
    
        sale.rens.forEach(async (ren) => {
            await findUser(ren.userFid);
        });
        console.log(uplines);
        return uplines;
    };
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search