Ответ 1
Там более одного способа сделать это:
Вложенные обратные вызовы
Без promises вы можете вложить обратные вызовы:
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);
}))
});
});
Это было бы самым простым способом, но обратите внимание, что это неэффективно, если эти два запроса могут выполняться параллельно.
Модуль async
Вы можете использовать модуль async
:
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);
});
});
Смотрите: https://caolan.github.io/async/docs.html#parallel
Но это может быть не самым удобным способом.
ES2017 async
/await
Самый гибкий способ сделать это, если у вас есть 30 вызовов сделать, будет:
- Используйте функции, которые возвращают promises вместо функций, которые принимают обратные вызовы
- Использовать async/await, если вы можете или, по крайней мере, создавать сопрограммы на основе генераторов
- Ожидание promises (или выход promises), когда логика должна выполняться последовательно
- Используйте
Promise.all()
для всего, что можно сделать параллельно
С асинхронным/ожиданием ваш код может выглядеть так:
// in sequence:
var make = await collection.distinct('make.name');
var model = await collection.distinct('model');
// use 'make' and 'model'
Или:
// in parallel:
var array = await Promise.all([
collection.distinct('make.name'),
collection.distinct('model'),
]);
// use array[0] and array[1]
Большим преимуществом async
/await
является обработка ошибок:
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
}
Вы можете использовать его только внутри функции, созданной с помощью ключевого слова async
. Для получения дополнительной информации см.:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
Для поддержки в браузерах см.
Для поддержки в Node см.
В местах, где у вас нет встроенной поддержки async
и await
, вы можете использовать Babel:
или со слегка отличающимся синтаксисом, основанным на генераторе, как в co
или сопрограмме Bluebird:
Смотрите эти ответы для получения дополнительной информации:
- try/catch блоки с асинхронным/ожиданием
- node.js ~ конструирование последовательности цепочек Promise разрешает
- Как выполнять функции генератора в параллельном режиме?
- node.js ~ конструирование последовательности цепочек Promise разрешает
- Использование async/wait + Bluebird для promisifyAll
- jQuery: вернуть данные после успеха ajax-звонка