1

after reviewing a number of questions around for/foreach loops I am still not able to get an output of a promise.all batch of functions.

The goal is to call each iteration of doSleepNow() synchronously, but wait in the Promise.all until all results are in before continuing with a .then()

in the below simplified code extract output_A should be giving four versions of doSleepNow().myTimeRes, however I get

myFun1 msg:  All array for myFun1 done
promToCall outputs (myTimeRes) :  [
  [ [Function: promToCall] ],
  [ [Function: promToCall] ],
  [ [Function: promToCall] ],
  [ [Function: promToCall] ]
]

what am I missing to have the Promise.all trigger each loop of doSleepNow()

*Note: using sleep fn as functional stub only

const myArr = [
  {"hello":"Bob"},
  {"hello":"Jane"},
  {"hello":"Elvis"},
  {"hello":"Zac"}
]
var myOutPromArr = [];
    
const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs));
    
async function doSleepNow(waittime, loopnum) {
    return new Promise((resolve, reject) => {
        var now = new Date().toISOString();
        const inTime = "Time Start sleep for " + loopnum + " is : " + now;
        sleep(waittime).then(() => {
            const now = new Date().toISOString();
            const outTime = "Time End sleep for " + loopnum + " is : " + now;
            const myTimeRes = "myTime = " + inTime + " : " + outTime
            console.log("w" + inTime + " : " + outTime)
            resolve(myTimeRes)
        });
    })
}

async function myFun1(waittime) {
    return new Promise((resolve, reject) => {
        const myArrLen = myArr.length
        var arrCount = 0;
        myArr.forEach((value) => {
            arrCount++
            const promToCall = (waittime, arrCount) => new Promise(resolve => doSleepNow(waittime, arrCount))
            myOutPromArr.push([promToCall])
            if (myArrLen === arrCount) {
                resolve("All array for myFun1 done")
            }
        })
    })
}

myFun1(1000).then((status) => {
    console.log("myFun1 msg: ", status)
    sleep(5000).then(() => {
        Promise.all(myOutPromArr).then((values) => {
            console.log("promToCall outputs (myTimeRes) : ", values); // <== output_A
        })
    })
})
Keith
  • 22,005
  • 2
  • 27
  • 44
art vanderlay
  • 2,341
  • 4
  • 35
  • 64
  • You are storing an array of functions, not an array of Promises as you can see from your console output. I'll post an updated version as an answer in a moment. – cdimitroulas Mar 22 '23 at 12:23

2 Answers2

2

You can use Promise.all and you are creating an array of arrays. If you pass that to promise.all it'll not work.

const myArr = [
  { hello: "Bob" },
  { hello: "Jane" },
  { hello: "Elvis" },
  { hello: "Zac" },
];

const sleep = (waitTimeInMs) =>
  new Promise((resolve) => setTimeout(resolve, waitTimeInMs));

function doSleepNow(waittime, loopnum) {
  var now = new Date().toISOString();
  const inTime = "Time Start sleep for " + loopnum + " is : " + now;
  return sleep(waittime).then(() => {
    const now = new Date().toISOString();
    const outTime = "Time End sleep for " + loopnum + " is : " + now;
    const myTimeRes = "myTime = " + inTime + " : " + outTime;
    return myTimeRes;
  });
}

function myFun1(waittime) {
  return myArr.map((_, i) => doSleepNow(waittime, i));
}

const list = myFun1(1000);
console.log("myFun1 msg: ");
sleep(500).then(() => Promise.all(list)).then((values) => {
    console.log("promToCall outputs (myTimeRes) : ", values);
  });
Rahul Sharma
  • 9,534
  • 1
  • 15
  • 37
1

Your main issue is that your myOutPromArr function is an array of arrays of functions. What you want is an array of promises.

Here is a modified version of your code (trying to keep it as similar as possible to the original) which is more correct. I also took the time to simplify some code to use async/await.

const myArr = [
  {"hello":"Bob"},
  {"hello":"Jane"},
  {"hello":"Elvis"},
  {"hello":"Zac"}
]

    
const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs));
    
async function doSleepNow(waittime, loopnum) {
  let now = new Date().toISOString();
  const inTime = "Time Start sleep for " + loopnum + " is : " + now;
  await sleep(waittime)
  
  now = new Date().toISOString();
  const outTime = "Time End sleep for " + loopnum + " is : " + now;
  const myTimeRes = "myTime = " + inTime + " : " + outTime
  return myTimeRes;
}

async function myFun1(waittime) {
  const myArrLen = myArr.length
  var myOutPromArr = [];
  
  myArr.forEach((value, index) => {
    const promise = doSleepNow(waittime, index + 1)
    myOutPromArr.push(promise)
  })
  
  return myOutPromArr;
}

myFun1(1000).then((promises) => {
    sleep(5000).then(() => {
        Promise.all(promises).then((values) => {
            console.log("promToCall outputs (myTimeRes) : ", values); // <== output_A
        })
    })
})
cdimitroulas
  • 2,380
  • 1
  • 15
  • 22
  • marking this as accepted vs one line by @Rahul Sharma as I will do some extra work in `myFun1()`. Should be noted that one liner works as expected if you are looking for smaller code. – art vanderlay Mar 22 '23 at 12:38