Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to identify results in Promise.all()

I am creating a module that is executing tasks based on a config it receives. These tasks are asynchronous and are returning a promise. Currently there are only two tasks to handle, but if there are more coming up, I will run into a problem of identifying which result of Promise.all() belongs to which task.

Here is a snap of my current code:

let asyncTasks = [];
let result = {};

if (config.task0) {
    asyncTasks.push(task0(param));
}

if (config.task1) {
    asyncTasks.push(task1(param));
}

Promise.all(asyncTasks)
    .then(results => {

        // TODO: There has to be a prettier way to do this..
        if (config.task0) {
            result.task0 = results[0];
            result.task1 = config.task1 ? results[1] : {};
        } else if (config.task1) {
            result.task0 = {};
            result.task1 = results[0];
        } else {
            result.task0 = {};
            result.task1 = {};
        }

        this.sendResult(result)
    });

The config looks like this:

const config = {
    task0: true,
    task1: true
};

As mentioned in the code, there has to be a prettier and more scaleable way to identify which result is coming from which task, but I can't find anything regarding Promise.all() that could help with this.

How do I identify which value belongs to which promise if Promise.all() resolves?

like image 809
Marv Avatar asked Jan 31 '17 14:01

Marv


People also ask

How can I get all promise results?

all() The Promise. all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will fulfill when all of the input's promises have fulfilled, or if the input iterable contains no promises.

Does promise all return results in order?

Yes, the values in results are in the same order as the promises .

What is the fulfilled value of promise all ()?

all() Method: Fulfillment: The returned promise is fulfilled, If the passed iterable is empty, then this method returns an promise synchronously which is already resolved. If all of the passed promises are fulfill, the returned Promises are fulfilled asynchronously.


2 Answers

Promise.all resolves with an array of values, where each value's index in the array is the same as the index of the Promise in the original array passed to Promise.all that generated that value.

If you need anything more fancy you'll need to keep track of it yourself or use another library that offers such functionality (like Bluebird).

like image 132
rossipedia Avatar answered Nov 15 '22 00:11

rossipedia


There's really no need to use anything other than Promise.all. You're experiencing difficulty because the other structure of your program (config, and arbitrary link of config key to function) is pretty messy. You might want to consider restructuring the code altogether

const config = {
  task0: true,
  task1: true,
  task2: false
}

// tasks share same keys as config variables
const tasks = {
  task0: function(...) { ... },
  task1: function(...) { ... },
  task2: function(...) { ... }
}

// tasks to run per config specification
let asyncTasks = Object.keys(config).map(prop =>
  config[prop] ? tasks[prop] : Promise.resolve(null))

// normal Promise.all call
// map/reduce results to a single object
Promise.all(asyncTasks)
  .then(results => {
    return Object.keys(config).reduce((acc, task, i) => {
      if (config[task])
        return Object.assign(acc, { [prop]: results[i] })
      else
        return Object.assign(acc, { [prop]: {} })
    }, {})
  })

// => Promise({
//      task0: <task0 result>,
//      task1: <task1 result>,
//      task2: {}
//    })

Note: we can depend on the order of results because we used Object.keys(config) to create the input array of promises and Object.keys(config) again to create the output object.

like image 30
Mulan Avatar answered Nov 14 '22 23:11

Mulan