1

Given a situation where you have to get data from multiple async functions or promises, what is the best way to collect and persist the data so it can be used after all are complete. An example situation would be multiple database queries which need to get rendered in a single page.

I've come across the below code, which looks like a solid pattern to me, but being new to the async game am unsure.

function complexQuery(objectId) {
    var results = {};
    return firstQuery.get(objectId).then(function (result1) {
            results.result1 = result1;
            return secondQuery.find();
        })
        .then(function (result2) {
            results.result2 = result2;
            return thirdQuery.find();
        })
        .then(function (result3) {
            results.result3 = result3;
            return results;
        });
}

complexQuery(objectId)
    .then(function (results) {
        //can use results.result1, results.result2, results.result3
        res.render('dash', results); //example use
    });

What is the best way to handle this kind of situation?

Edit for clarification: Must be in series, queries may require information from a preceding promise result.

Ryhnn
  • 456
  • 1
  • 5
  • 16
  • If the queries must be in series, your code should reflect that. – Bergi Apr 04 '15 at 12:49
  • Is there anything that is not answered by the [canonical duplicate](http://stackoverflow.com/q/28250680/1048572)? I'm inclined to close, but feel free to edit and ask a more specific question - possibly with your real code. – Bergi Apr 04 '15 at 12:51

2 Answers2

2

The easiest way is to use Promise.all, which has the benefit of doing the queries in parallel:

function complexQuery(objectId) {
    return Promise.all([firstQuery.get(objectId),
                        secondQuery.find(),
                        thirdQuery.find()])
    .then(([result1, result2, result3] => {result1, result2, result3}); // ES6 syntax
    /* ES5 equivalent would be
    .then(function(results) {
        return {result1: results[0], result2: results[1], result3: results[2]};
    }); */
}

If you need to execute the queries in sequence (because they depend on each other), have a look at How do I access previous promise results in a .then() chain? where different strategies (such as the one given in your question, which imo is not a good one) are explained in depth.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

Best way is to store all your promises in an array and use Q.all() or the async equivalent which I think is the same to run a function after everything is complete

Ardenexal
  • 543
  • 6
  • 20
  • that will only work if the promises don't require information from each other. – Ryhnn Apr 04 '15 at 11:58
  • Are you using async. You can use async.series to run each sequentially so you can use information from the previous which is similar to what you already have – Ardenexal Apr 04 '15 at 12:02