The pyramid
The pyramid

Reputation: 323

run a callback function after forEach loop finish

how to callback timer() function after forEach loop is finished, using the same code. or is there is a better way to loop through each user with delay then after the loop is done, the timer() is called back using forEach.

  const usersProfile = () => {
  let interval = 1000;
  let promise = Promise.resolve();
  db.select('*').from('users')
    .returning('*')
    .then(users => {
      users.forEach((user, index) => {
        setTimeout(function(){

        }, index * 1000)
        db.select('*').from(`${user.name}`)
          .returning('*')
          .then(userdata => {
            userdata.forEach(data => {
                promise = promise.then(function(){
                  if(data.status === 'online'){
                    console.log(`${data.name} ${data.items} ${data.profile} ${data.images}`)
                  }
                return new Promise(function(resolve){
                    setTimeout(function(){
                      resolve();
                    }, interval)
                })
              })
            })
          })
      })
       timer();
    })
}
const timer = () => {
  setTimeout(usersProfile, 1000)
}
timer();

===============ALL THE ABOVE ARE MY OLD CODE ================ but thanks to https://stackoverflow.com/users/2404452/tho-vu it solved most of the problem but can i do this to serve the purpose of the app

const usersProfile = async () => {
  let interval = 1000;

  const delayPromise = (data, delayDuration) => {
    return new Promise((resolve) => {
      setTimeout(() => {
        if(data.status === 'online'){
          console.log(`${data.name} ${data.items} ${data.profile} ${data.images}`);
          resolve();
        }
      }, delayDuration)
    });
  };

 const userInfo = (data, delayDuration) => {
    return new Promise((resolve) => {
      setTimeout(() => {
          console.log(`${data.info}`);//info about user from his table each user has his own table besides users table that has only the user tables
          resolve();
      }, delayDuration)
    });
  };
  try {
    const userData = await db.select('*').from('users').returning('*');
    const promises = userData.map((data, index) => delayPromise(data, index * interval));
    const userData = await db.select('*').from(`${data.name}`).returning('*');
    const info = userData.map((data, index) => userInfo(data, index * interval));
    await Promise.all(promises);
    // here you can write your effects
  } catch (e) {
    console.log(e);
  }
}

Upvotes: 0

Views: 740

Answers (2)

blaz
blaz

Reputation: 4068

Another approach using async-await to avoid callback hell.

const usersProfile = async () => {
  let interval = 1000;

  const delayPromise = (data, delayDuration) => {
    return new Promise((resolve) => {
      setTimeout(() => {
        if(data.status === 'online'){
          console.log(`${data.name} ${data.items} ${data.profile} ${data.images}`);
          resolve();
        }
      }, delayDuration)
    });
  };

  try {
    const userData = await db.select('*').from('users').returning('*');
    const promises = userData.map((data, index) => delayPromise(data, index * interval));
    await Promise.all(promises);
    // here you can write your effects
  } catch (e) {
    console.log(e);
  }
}

Upvotes: 2

orpris12
orpris12

Reputation: 156

it is hard for me to fully understand what you wanted to accomplish through the code, but I will try to explain what you can do to solve the issue.

First of all, if you want to wait for multiple promises, you should use Promise.all and not promise = promise.then

You can do this as so:

let promises = [];
users.forEach((user, index) => {
   let promise = db.select(*).from('users') //should return a promise
   promises.push(promise);
});

//promises have already started to execute (in parallel)

Promise.all(promises)
.then(() => console.log('all promises finished successfully'))
.catch((e) => console.error('received error at one of the promises'));


 // when the program arrives here we know for a fact that either all promises executed successfully or one of the promises failed

timer();

Explanation: because promises execute asynchronously the forEach() function does not wait for any of the promises created to finish, so the solution is to wait for all of them at then after the entire loop.

This means the promises are created, and are being executed while the forEach() loop executes, in parallel, and when the program reaches Promise.all it stops and waits for all of them to finish.

Second, I would strongly advice you to use functions as a way to simplify your code, that way it would be easier for you to grasp every thing that is happening, even if its complicated.

Good luck !

Upvotes: 0

Related Questions