1

I am trying to get all the results from a map with time out.

I’ve tried to use promise.all() But it didn’t succeed because of the setTimeout function.

I will be happy if someone can look oh my code and suggest how to do it right.

Thank you very much.

new Promise(async (resolve, reject) => {
  Promise.all(
    items.map(async (item, i) => {
      await setTimeout(async () => {
        return await SendMail(item);
      }, 5000 * i);
    })
  ).then((mailsRes) => {
    resolve(mailsRes);
  });
});
Penny Liu
  • 7,720
  • 5
  • 40
  • 66
  • looks like you want to fire all emails at once right? otherwise you don't need Promise.all – Waelsy123 Mar 30 '21 at 14:33
  • 1
    to me it's strange that you use Promise.all and setTimeout with cumulative timeout. – Waelsy123 Mar 30 '21 at 14:34
  • Yes I want to fire all emails at once But I have to set a timeout because their server he’s not capable of receiving bunch of emails at once So I’m taking a little breaks between them – Meir Peratz Mar 30 '21 at 14:38
  • 1
    then I recommend to simply use async with for loop, for sure you don't need to use Promise.all. the idea of promise all to run all promises at once and as you mentioned you want the opposite – Waelsy123 Mar 30 '21 at 14:46
  • I will write an easy to read method for you in a minute as an answer – Waelsy123 Mar 30 '21 at 14:46
  • 1
    `await setTimeout`? That doesn't work. setTimeout doesn't return a promise. Probably a duplicate of this https://stackoverflow.com/questions/39538473/using-settimeout-on-promise-chain – Wyck Mar 30 '21 at 14:59
  • please check the answer below I added sendEmails and sleep functions – Waelsy123 Mar 30 '21 at 15:25

3 Answers3

1

Simply loop through your items and sleep for x seconds (5 in this example) after sending each email.

const sleep = (milliSeconds) => {
    return new Promise((resolve, _reject) => {
      setTimeout(() => {
        resolve()
      }, milliSeconds)
    })
  }

const sendEmails = async (items) => {
    for (let i = 0; i < items.length; i++) {
        const currentItem = items[i];
        await SendMail(currentItem);
        await sleep(5000)
    }
}

as you see sendEmails is an async function then you can call it by:

await sendEmails(items)
Waelsy123
  • 528
  • 2
  • 12
0

Not sure what you are trying to achieve but you probably need this-

async function timeout(interval) {
    return new Promise(resolve => {
    setTimeout(resolve, interval);
  });
}

new Promise( async (resolve, reject) => {

  Promise.all(items.map( async (item, i)=>{ 
    await timeout(5000 * i).then(() => {
        return await SendMail(item);
    });
  }))
  .then(mailsRes => {
    resolve(mailsRes)
  }) 
          
});

The problem is that setTimeout is resolved immediately and you get a timeout canceller in the next callback.

arunkjn
  • 3,931
  • 3
  • 18
  • 31
-1

If I understand you correctly, that might do the trick:

function delayedSendMail(item, i) {
  return new Promise(resolve => setTimeout(() => resolve(SendMail(item)), 5000 * i));
}

Promise.all(items.map((item, i) => delayedSendMail(item, i)))
  .then(mailResults => {
    // handle results
  });