0

I'm currently a little stuck with a race condition, and I'm pulling my hair out. Essentially, I'm querying an API, adding the results to the DB, then doing stuff with the returned/saved data.

I'm less asking about this specific problem, and more the design pattern of how to fix this sort of issue. The line p.push(formatter.createAccounts(account, id)); might run upto 1000 times, and might take 20 seconds or so.

Any ideas on what I'm doing wrong will be super helpful

Thanks, Ollie


// get all users
Promise.all(updatedUsers)
.then(() => {
  // create an array of promises
  const p = [];

  users.then((user) => {
    ...
    ids.forEach((id) => {
      const accounts = foo.getAccounts(id, true); // returns a promise
      accounts.then((account) => {
        // add the return data from here to the promise array at the bottom
        p.push(formatter.createAccounts(account, id));
      });
    });
  });

  // this would ideally be a promise array of the data from above - but instead it just evaluates to [] (what it was set to).
  Promise.all(p).then(() => {
    // do my stuff that relies on the data here
  })
});
Ollie
  • 1,104
  • 7
  • 24
  • 45
  • Where are `users` & `ids` coming from? – Mark Nov 27 '17 at 17:02
  • Maybe you can post some coherent sample code, currently this has syntax errors and it's unclear where half the variables come from. – Tomalak Nov 27 '17 at 17:03
  • Possible duplicate of [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – James Thorpe Nov 27 '17 at 17:12
  • Re: that dupe - in this case, `p` is the variable you're altering within the async function. – James Thorpe Nov 27 '17 at 17:13
  • Sorry all - I wasn't really aiming for runnable code - I was mostly just trying to use something to demonstrate my problem. Essentially I'm doing something intensive that i'd like to make sure runs in the correct order - and it seems that the promise.all isn't 'waiting around' until the promises have been pushed into it – Ollie Nov 27 '17 at 17:14
  • 2
    No `Promise.all()` doesn't wait for the array to be filled, it waits for the promises *in an array* to resolve. That array needs to be filled *before* calling `Promise.all()` – Mark Nov 27 '17 at 17:15
  • It's not at all unimportant to have coherent sample code. There is no way of refactoring non-working code. Also the question must make sense to your readers now and to future visitors. For example - where does `ids` come from? – Tomalak Nov 27 '17 at 17:18

1 Answers1

2

The problem is that you are not including the foo.getAccounts promise into your promises array. Modified version:

Promise.all(updatedUsers)
.then(() => {

  users.then((user) => {
    return Promise.all(ids.map(id => {
      //for each ID we return a promise
      return foo.getAccounts(id, true).then(account => {
        //keep returning a promise
        return formatter.createAccounts(account, id)
      })

    }).then((results) => {
      //results is an array of the resolved values from formatter.createAccounts
      // do my stuff that relies on the data here
    })
  })

 //rest of closing brackets
yBrodsky
  • 4,981
  • 3
  • 20
  • 31