kaitlyn
kaitlyn

Reputation: 76

Callback inside Promise.all

I have a doubt in using Promise.all. I need to have three functions with callbacks. So I am writing these three function inside Promise.all and then get all three functions result in .then() of Promise.all. Is it a proper way or is there any other way?

Upvotes: 0

Views: 1287

Answers (2)

Tom
Tom

Reputation: 1507

You need to wrap the callbacks in a promise to resolve them all with Promise.all

So:

Promise.all([
    new Promise(resolve => client.query(q1, function(err, result) { resolve(result); }) ),
    new Promise(resolve => client.query(q2, function(err, result) { resolve(result); }) ),
    new Promise(resolve => client.query(q3, function(err, result) { resolve(result); }) )
]).then(([q1, q2, q3]) => {
   //do something with results
}).

If you need to handle errors you'll need to reject on error.

Hope that helps.

Upvotes: -1

T.J. Crowder
T.J. Crowder

Reputation: 1074335

It sounds like you're doing it right, yes; it would have been better if you'd shown code.

But let's say you want to start three processes, which are started by doThis(), doThat(), and doTheOther(). You handle it like this:

Promise.all([
    doThis(),
    doThat(),
    doTheOther()
])
.then(([thisResult, thatResult, theOtherResult]) => { // The destructuring is optional, of course
    // ...use them...
})
.catch(error => {
    // ...handle/report error...
});

Key bits:

  1. You pass an iterable to Promise.all (I used an array above)
  2. You receive the results in the same order as the iterable (regardless of what order things completed in)
  3. Promise.all's promise rejects if any of the operations rejects.

In a comment you've posted this code:

Promise.all([
    client.query(q1,function(err,res){ dosomething();}),
    client.query(q2,function(err,res){ dosomething();})
])
.then(() => {
    dosomething()};
})  // <== Added missing }
.catch(e => {
    console.log(e); // <== Added missing ;
}); // <== Added missing ;

That looks incorrect. Normally, when a function accepts a callback like you show query doing, it doesn't return a promise. Check your documentation for the query call you're making.

If it returns a promise, then you'd use it like this:

Promise.all([
    client.query(q1).then(dosomething),
    client.query(q2).then(dosomething)
])
.then(() => {
    dosomething()};
})  // <== Added missing }
.catch(e => {
    console.log(e); // <== Added missing ;
}); // <== Added missing ;

...assuming you want doSomething to be called only when the query succeeds (your code was calling it whether the query succeeded or failed).

If query doesn't return a promise, you'd wrap it in something that does, like this:

function doQuery(client, q) {
    return new Promise((resolve, reject) => {
        client.query(q, function(err, res) {
            if (err) {
                reject(err);
            } else {
                resolve(res);
            }
        });
    });
}

then using that:

Promise.all([
    doQuery(client, q1).then(doSomething),
    doQuery(client, q2).then(doSomething)
])
.then(() => {
    dosomething()};
})  // <== Added missing }
.catch(e => {
    console.log(e); // <== Added missing ;
}); // <== Added missing ;

(Again, I've assumed doSomething should only be called when the query was successful.)

These days, lots of APIs are adding promise features. Also, there's util.promisify to wrap callback-style API functions in promises. Here's how you'd use that with your code

const doQuery = util.promisify(client.query.bind(client)); // Note the .bind(client)
Promise.all([
    doQuery(q1).then(doSomething),
    doQuery(q2).then(doSomething)
])
.then(() => {
    dosomething()};
})  // <== Added missing }
.catch(e => {
    console.log(e); // <== Added missing ;
}); // <== Added missing ;

Upvotes: 3

Related Questions