Home > Back-end >  Javascript promises Nodejs
Javascript promises Nodejs

Time:02-17

My code is similar to the below example

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

let Promises = [];

for (let i = 0, p = Promise.resolve(); i < 10; i  ) {
    p = p.then(() => delay(Math.random() * 10))
        .then(() => console.log(i));
}
console.log("Done");

// "Done" is getting printed before the loop executes, want it after the loop executes completely

Here is the sudo code I'm trying to build

sql query promise {
    const mainArray = []
    // some processing
        
    for loop {
            
        Step1
        const temp = {}
        // building a temp object
            
        Step2
        another sql query promise {
            // further build temp object
            // after the temp object is fully built
            mainArray.add(temp);
        }
    }
    Step3
    // once the loop finishes 
    return mainArray        
}

Execution order is - step1, step3 then step2 However, how do I make it work like step1, step2, then step3

CodePudding user response:

I would wrap all of this in an async function to be able to use the await keyword, and then for each instance of the loop, wrap it in a promise that resolves after your delay

const delay = ms => new Promise(resolve => 
  setTimeout(resolve, ms)
);
const getRandomInt=(min,max)=>{
    let range = max - min;
    return parseInt(Math.random()*range) min
}
const sequentialLoop = async ()=>{
  let thingsToDo = [1,2,3,4,5];
  for (let i =0; i < thingsToDo.length; i  ){
    await new Promise (async resolve=>{
      console.log('item',i,'started');
      // to get a noticeable delay
      let minDelay = 700 i*200
      await delay(getRandomInt(minDelay,minDelay*2))
      console.log('item',i,'finished')
      resolve()
    })
  }
}
//using async
async function main(){
  await sequentialLoop();
  console.log('Done')
} 
main()
/*
// using then
sequentialLoop().then(()=>
  console.log('Done')
)
*/

CodePudding user response:

If I understand correctly your question... You whish to wait for an amount of promises (DB requests) to fill a results array... An then, use that array.

So in you example, the delay function is just to simulate a DB request. I improved it a little by also simulating a response and making sure it would be added to a results array.

The keys to acheive it are async/await and Promise.all().

See comments throughout the code.

// A function to simulate a DB request
// Notice we<re passing it the for loop index and the result array
const delay = (ms, i, results) =>
  new Promise((resolve) =>
    setTimeout(() => {
      console.log(i   " is about to resolve...");

      // Simulating a response and pushing it to the result array
      let fakeResult = { RequestNumber: i, response: Math.random() * 100 };
      results.push(fakeResult);

      resolve();
    }, ms)
  );

async function main() {
  let promisesList = [];
  let results = [];
  console.log("Start!");

  // Initiate every requests
  for (let i = 0; i < 10; i  ) {
    // Push some promises here... To simulate some DB requests
    promisesList.push(delay(Math.random() * 10, i, results));
  }

  // Await for all promises to resolve
  await Promise.all(promisesList);

  // Enjoy the results
  console.log(results);

  // You even can have them in the right order
  let resultsOrdered = [...results].sort(
    (a, b) => a.RequestNumber - b.RequestNumber
  );
  console.log(resultsOrdered);

  console.log("Done");
}

main();

The console is more enjoyable in CodePen

  • Related