There's more than one way to do it:
Nested callbacks
Without promises you could nest the callbacks:
router.post('/search', (req, res) => {
var collection = db.get().collection('styles')
var data = [];
collection.distinct('make.name', (err, docs) => {
if (err) {
// ALWAYS HANDLE ERRORS!
}
data.push({'make': docs });
collection.distinct('model', (function (err, docs) {
if (err) {
// ALWAYS HANDLE ERRORS!
}
data.push({'model': docs });
res.send(data);
}))
});
});
This would be the easiest way, but note that it is not efficient if those two requests could be done in parallel.
The async
module
You can use the async
module:
router.post('/search', (req, res) => {
var collection = db.get().collection('styles')
var data = [];
async.parallel({
make: cb => collection.distinct('make.name', cb),
model: cb => collection.distinct('model', cb),
}, (err, responses) => {
if (err) {
// ALWAYS HANDLE ERRORS!
}
data.push({'make': responses.make });
data.push({'model': responses.model });
res.send(data);
});
});
See: https://caolan.github.io/async/docs.html#parallel
But this may still not be the most convenient method.
ES2017 async
/await
The most flexible way of doing that if you have 30 calls to make would be to:
- Use functions that return promises instead of functions that take callbacks
- Use async/await if you can or at least generator based coroutines
- Await on promises (or yield promises) when the logic needs to run in sequence
- Use
Promise.all()
for anything that can be done in parallel
With async/await your code could look like this:
// in sequence:
var make = await collection.distinct('make.name');
var model = await collection.distinct('model');
// use 'make' and 'model'
Or:
// in parallel:
var array = await Promise.all([
collection.distinct('make.name'),
collection.distinct('model'),
]);
// use array[0] and array[1]
A big advantage of async
/await
is the error handling:
try {
var x = await asyncFunc1();
var array = await Promise.all([asyncFunc2(x), asyncFunc3(x)]);
var y = asyncFunc4(array);
console.log(await asyncFunc5(y));
} catch (err) {
// handle any error here
}
You can only use it inside of a function created with the async
keyword. For more info, see:
For support in browsers, see:
For support in Node, see:
In places where you don't have native support for async
and await
you can use Babel:
or with a slightly different syntax a generator based approach like in co
or Bluebird coroutines:
See those answers for more info: