0

I am trying to:

  1. Retrieve an array of objects containing account information from my Database,
  2. Use the account_id from those accounts to make a fetch request to an external API for each of the accounts and retrieve transactions
  3. Loop over every single transaction in each account and save it one-by-one into my database.
  4. Send the newly-saved transactions back to the frontend as a response to the API call

Everything works great, except that the last part of my code that is outside of the two loops runs before the async tasks finish.

My question is - how do I make sure that the last part of the code (console.log and the DB query that retrieves the newly-saved transactions) executes after all the async tasks finish?

I was trying to use callbacks / promises and follow other guides, but I did not manage to get it to work, so I would be grateful for some help!

I have the following Express.js code:

router.post("accounts/transactions", async (req, res) => {
  //user id sent from frontend
  const user_id = req.body.user_id;
  //Find accounts by user_id in DB
  const accounts = Account.find({ user_id: user_id }).then((accounts) => {
    return accounts;
  });
  //Once accounts retrieved from DB, loop over them and fetch transactions for each account
  (await accounts).forEach(async (account) => {
    const url = `https://someExternalApi.whatever/${account.accountId}/transactions`;
    const options = {
     //fetch request options
    };

    const response = await fetch(url, options)
      .then((res) => res.json())
      .catch((e) => {
        console.error({
          message: "Error!",
          error: e,
        });
      });

    //Once transactions for a single account are retrieved from external API, 
    //loop over them and save them one-by-one to DB

    (await response).transactions.booked.forEach(async (transaction) => {
      const filter = {
        transactionId:
          transaction.transactionId
      };
      const mongooseOptions = { upsert: true, new: true };
      const update = {
        user_id: user_id,
        //...other keys-value pairs for transaction record
        updated: Date.now(),
      };

      //Save single transaction to DB
      Transaction.findOneAndUpdate(filter, update, mongooseOptions)
        .then(
          console.log(
            `Transaction ${
              transaction.transactionId
            } saved!`
          )
        )
        .catch((error) => console.log(error));
    });
  });
  //The problem is that the below runs before the above async operations are finished
  console.log("All transactions updated!");
  Transaction.find({ user_id: user_id }).then((transactions) => {
    res.json(transactions);
  });
});

Thanks!

Glemin5011
  • 21
  • 2
  • See the answers to [the](https://stackoverflow.com/questions/37841721/wait-for-multiple-promises-to-finish) [linked](https://stackoverflow.com/questions/45596384/how-to-handle-multiple-async-requests) [questions](https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop). Basically, instead of throwing away the promise each of your `async` functions returns (because `forEach` ignores the return value of callbacks), use those promises (often by using `map` instead and then using `Promise.all` on the result). – T.J. Crowder Jan 18 '22 at 17:51
  • Thanks a lot, solved it!! – Glemin5011 Jan 18 '22 at 18:05

0 Answers0