0

Is there a way to use the new "async" javascript keyword to replace async.map from the async module? Basically I want to avoid using the async module if possible. For example, read many files at once, then do something when all the files have been read.

Dawn
  • 163
  • 2
  • 2
  • 9
  • 6
    [`Promise.all`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) – CRice Mar 20 '18 at 20:20
  • 1
    Use `Promise.all()` for getting notified when N operations running in parallel are all done. There's also the Bluebird promise library which has useful features like `Promise.map()` and `Promise.promisifyAll()`. See [Are there still reasons to use promise libraries now that we have ES6](https://stackoverflow.com/questions/34960886/are-there-still-reasons-to-use-promise-libraries-like-q-or-bluebird-now-that-we/34961040#34961040). – jfriend00 Mar 20 '18 at 21:20

2 Answers2

3

Yes, generally you can do this with Promise.all.

let urls = [...];

let promises = urls.map(function(url) {
    return fetch(url).then(result => result.json()); // or whatever
});

Promise.all(promises).then(function(results) {
    // deal with the results as you wish
});

Or, to do it in a one-liner:

Promise.all(urls.map(url => fetch(url).then(res => res.json()))).then(function(results) {
    // deal with the results as you wish
});

Though that ain't easy to read, I fear...

It's not quite as sleek as async.map, though of course writing an appropriate wrapper would not be hard.

lonesomeday
  • 233,373
  • 50
  • 316
  • 318
  • 1
    I think it's much easier to read than `async.map` with its callback-passing. Also you can use `async function(url) { return (await fetch(url)).json(); }` (or something similar) for the callback – Bergi Mar 20 '18 at 22:00
  • If you want to use async keyword you can too : `const results = await Promise.all(urls.map(url => ...))` – naholyr Mar 20 '18 at 22:09
  • Well, the question does say ES6, but yes, they both improve things. – lonesomeday Mar 20 '18 at 22:10
  • Or, for absolute concision (and obfuscation): `let results = await Promise.all(urls.map(async url => (await fetch(url)).json()));` – lonesomeday Mar 20 '18 at 22:19
0

Helper function:

async function asyncMap(array, callback) {
  let results = [];
  for (let index = 0; index < array.length; index++) {
    const result = await callback(array[index], index, array);
    results.push(result);
  }
  return results;
}

Sample usage:

const titles = await asyncMap([1, 2, 3], async number => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/todos/${number}`
  );
  const json = await response.json();
  return json.title;
});

Inspired by this async forEach

Craig Myles
  • 5,206
  • 3
  • 40
  • 37