Skip to content

Loop asynchronosly through array

I have following code:

var obj = {
   "slot1": ["1", "2"],
   "slot2": ["7", "5"],
   "slot3": ["12", "213"],
};

for (var key of Object.keys(obj )) {
   obj[key].reduce((chain, user_id) => {
    return chain
    .then(() => async_things_happen)
    .then(result => {
        other_things_happen
    });
  }, Promise.resolve()).then(() => {

  });
}

As you can see this does not work. So the content of the for loop works pretty well. It goes through the array and works well, but the for loop itself is the problem. How can I get the for loop wait for the inner content to finish before going to the next key?
The timeline should be as followed: key(slot1) --> .reduce stuff --> key(slot2) --> .reduce stuff --> key(slot3) --> .reduce stuff --> fire finish
I experimented with many different structures and can’t find a solution.

ADDITION

async function test(obj) {
  return dosomething.then(()=> {
    return Object.keys(obj).reduce((chain, key) => {
      return chain.then(() => {
        return obj[key].reduce((chain, user_id) => {
            return chain.then(() => {dosomething})
        }, Promise.resolve());
      }, Promise.resolve());
    }).then(() => {
      console.log("LOOPED TROUGH ALL KEYS AND ARRAYS");
    });
  });
} 

Thanks in advance,
filip.

Answer

Your .reduce strategy for the inner loop is good but the outer loop is still synchronous, and starts a promise chain for each key all at the same time. Apply the same thing to the outer loop:

Object.keys(obj).reduce((chain, key) => {
    return chain.then(() => {
        return obj[key].reduce((chain, user_id) => {
            return chain.then(() => asyncStuff())
        }, Promise.resolve())
}, Promise.resolve())

Or with async/await it becomes a friendlier loop:

for (var key in obj) {
    for (var user_id of obj[key]){
        await asyncStuff()
    }
}