chtefi
6/30/2015 - 10:46 PM

Async, Await, Promises, foreachAsync

Async, Await, Promises, foreachAsync

const echo = (msg, delay = 50) => new Promise((resolve) => setTimeout(() => resolve(msg), delay));
const echoUpperCase = (msg, delay = 50) => new Promise((resolve) => setTimeout(() => resolve(new Date().toISOString() + ' ' + msg.toUpperCase()), delay));
const foreachAsync = async (array, cb) => { for (let i = 0, l = array.length; i < l; i++) await cb(array[i]);};

const severalDelays = async (...msgs) => {
  //msgs; // BABEL HACK https://github.com/babel/babel/issues/1882
  // var ret = '';
  // we can't use forEach because the await is inside another method.
  // so we have to async the function
  // but if it's async, we need to await it
  // but it's not us that wrote forEach, so we can't.
  // msgs.forEach((item) => {
  //   let val = await echo(item);
  //   ret += ' ' + val;
  // });
  
  // that leads us to :
  // for (var i = 0; i < msgs.length; i++) {
  //   var item = msgs[i];
  //   let val = await echo(item);
  //   ret += val + ' ';
  // }
  
  // but we are smart, so we create our own forEachAsync
  await foreachAsync(msgs, async (msg) => console.log(await echoUpperCase('1 ' + msg)));

  // but we can use for..of actually
  for (const msg of msgs) {
    console.log(await echoUpperCase('2 '+ msg)); // await belongs to the main function
  }
  
  // Or play it concurrent
  await Promise.all(msgs.map(async (msg) => console.log(await echoUpperCase('3 ' + msg))));
  
  // Basically, Promise.all should be almost always use, because it naturally "await" its args
  return await Promise.all(msgs.map(async (msg) => 'hello ' + await echoUpperCase('4 ' + msg)));
};

severalDelays('first!', 'second!', 'third!').then((res) => {
  console.log('done!', res);
});