Bluebird promises – how to explode an array, then map it?

If I have an array:

['one.html','two.html','three.html']

how could I explode that array, apply a chain of promises to it, then combine it back together again? At the moment my code is like this:

  • Bluebird Promise serial iteration, and resolve to modified array?
  • How to ensure correct “this” with Promise.promisify?
  • Nodejs parallel with promise
  • How to run after all javascript ES6 Promises are resolved
  • Promises not working on IE11
  • Downloading files with node.js, streams, and promises
  • Promise.map(['one','two','three'], function(i) {
        dbQuery('SELECT ' + i);
    }).then(function(results) {
        // This has an array of DB query results
    });
    

    I’m imagining something like:

    Promise.map(['one','two','three'], function(i) {
        dbQuery('SELECT ' + i);
    })
    .explode()
    .then(function(result) {
        // Individual result
    })
    .combine()
    .then(function(results) {
        // Now they're back as an array
    });
    

    Now, I know Bluebird doesn’t have these functions, so I’m wondering what the correct Promise-y way is of doing this?

  • Bluebird Promise: Nested or conditional chains
  • Promises with fs and bluebird
  • How can you retry after an exception in Javascript when using promises?
  • Best way to handle nested Promises (bluebird)
  • Does .then(Promise.mapSeries(…)) behave differently than .then(function() { return Promise.mapSeries(…); })?
  • What is the explicit promise construction antipattern and how do I avoid it?
  • 2 Solutions collect form web for “Bluebird promises – how to explode an array, then map it?”

    You can use a chain of maps:

    Promise.map(['one','two','three'], function(i) {
        return dbQuery('SELECT ' + i);
    }).map(function(result) {
        // Individual result
    }).map(function(result) {
        // Individual result
    }).map(function(result) {
        // Individual result
    }).then(function(results) {
        // Now they're back as an array
    });
    

    However the above will not be as concurrent as

    Promise.map(['one','two','three'], function(i) {
        return dbQuery('SELECT ' + i).then(function(result) {
            // Individual result
        }).then(function(result) {
            // Individual result
        }).then(function(result) {
            // Individual result
        })
    }).then(function(results) {
        // Now they're back as an array
    });
    

    Bluebird does in fact have this. but it doesn’t modify the array: Promise.each()

    var transformed = []
    
    Promise.map(['one','two','three'], function(i) {
        return dbQuery('SELECT ' + i);
    })
    .each(function(result) {
        // This is repeating access for each result
        transformed.push(transformResults(result));
    })
    .then(function(results) {
        // here 'results' is unmodified results from the dbQuery
        // array doesn't get updated by 'each' function
        // here 'transformed' will contain what you did to each above
        return transformed
    });
    

    Chaining maps or adding more promises off dbQuery works well, but each() could be advantage if you only want a side effect when touching individual results