Search code examples
javascriptnode.jspromisees6-promise

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?


Solution

  • 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.