有不止一种方法可以做到这一点:
嵌套回调
如果没有承诺,您可以嵌套回调:
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);
}))
});
});
这将是最简单的方法,但请注意,如果这两个请求可以并行完成,则效率不高。
The async
module
您可以使用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 https://caolan.github.io/async/docs.html#parallel
但这可能仍然不是最方便的方法。
ES2017 async
/await
如果您要拨打 30 个电话,最灵活的方法是:
- 使用返回 Promise 的函数而不是接受回调的函数
- 如果可以或者至少使用基于生成器的协程,请使用 async/await
- 当逻辑需要按顺序运行时,等待 Promise(或 Yield Promise)
- Use
Promise.all()
对于任何可以并行完成的事情
使用 async/await 你的代码可能如下所示:
// 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]
一个很大的优点是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/Statements/async_function
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
有关浏览器的支持,请参阅:
- http://caniuse.com/async-functions http://caniuse.com/async-functions
有关 Node 中的支持,请参阅:
- http://node.green/#ES2017-features-async-functions http://node.green/#ES2017-features-async-functions
在没有本地支持的地方async
and await
你可以使用巴贝尔:
- https://babeljs.io/docs/plugins/transform-async-to-generator/ https://babeljs.io/docs/plugins/transform-async-to-generator/
或者使用稍微不同的语法基于生成器的方法,例如co
或 Bluebird 协程:
- https://www.npmjs.com/package/co https://www.npmjs.com/package/co
- http://bluebirdjs.com/docs/api/promise.coroutine.html http://bluebirdjs.com/docs/api/promise.coroutine.html
请参阅这些答案以获取更多信息:
- 带有 async/await 的 try/catch 块 https://stackoverflow.com/questions/40884153/try-catch-blocks-with-async-await/40886720#40886720
- node.js ~ 构造 Promise 解析的链式序列 https://stackoverflow.com/questions/43238039/node-js-constructing-chained-sequence-of-promise-resolves/43238119#43238119
- 如何并行运行生成器函数? https://stackoverflow.com/questions/42768461/how-to-run-generator-functions-in-parallel/42768639#42768639
- node.js ~ 构造 Promise 解析的链式序列 https://stackoverflow.com/questions/43238039/node-js-constructing-chained-sequence-of-promise-resolves/43238119#43238119
- 使用 async/await + Bluebird 来 promisifyAll https://stackoverflow.com/questions/43096728/using-async-await-bluebird-to-promisifyall/43096840#43096840
- jQuery:ajax调用成功后返回数据 https://stackoverflow.com/questions/5316697/jquery-return-data-after-ajax-call-success/5316805#5316805