2

Given the following code

class SomeClass {
  async someFunc() {
    const urlParameters = [0, 1, 2];
    const batchAjaxResult = await urlParameters.map((parameter) => { 
        const result = await $.get(`someUrl/${parameter}`);
        return {
          parameter,
          result
        }
     });

  console.log(batchAjaxResult);

  }
}

JavaScript will return an Array of resolved Promises instead of the actual Promises result.

This is probably due to Array.map() not being implemented as a Promise.

Is there a Promise-based version of Array.map?

This is question differs from How to return the response from an asynchronous call, because it's about How to return batched responses wrapped inside Array.map.

Community
  • 1
  • 1
Tobias Mühl
  • 1,788
  • 1
  • 18
  • 30
  • Specifically look towards the bottom of [this answer](http://stackoverflow.com/a/30180679/542251) – Liam Aug 01 '16 at 09:17
  • 1
    @Liam I'm already using the mentioned ES7 async/await syntax. The problem only occurs when Array.map'ing over them. `const X = await Array.map(...)` seems to not be implemented yet. – Tobias Mühl Aug 01 '16 at 09:21
  • 2
    You can only `await` a promise, not an array. Try `await Promise.all(array)`. – jib Aug 01 '16 at 17:42

2 Answers2

3

You could use this simple function which chains the promises to achieve sequential execution:

function asyncMap(arr, mapper) {
  var q = Promise.resolve();
  return Promise.all(arr.map(v => q = q.then(() => mapper(v))));
}


// Usage

asyncMap([1, 2, 3], v => {
  return new Promise(resolve => {
    console.log("Start " + v);
    setTimeout(() => {
      console.log("End " + v);
      resolve("foo" + v);
    }, 500);
  });
}).then(a => console.log(a));
Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97
2

By writing this question I managed to get down to the root of the problem.

It seems like Bluebird has such an feature called Promise.map

Similarily there is a native implementation called Promise.all that creates a "bulk Promise"

I changed the code as follows and it's working:

class SomeClass {
  async someFunc() {
      const urlParameters = [0, 1, 2];
      const batchAjaxResult = await Promise.all(
          urlParameters.map(async (parameter) => {
            const result = await $.get(`someUrl/${parameter}`);
            return {
              parameter,
              result
            }
         })
      );
      console.log(batchAjaxResult);

  }
}
Tobias Mühl
  • 1,788
  • 1
  • 18
  • 30