[英]How do I send multiple queries from one endpoint with Express?
我试图多次查询数据库,并构造一个对象,该对象将数据库中的每个响应存储在一个字段中。 这是我的代码:
router.post('/search', (req, res) => {
var collection = db.get().collection('styles')
var data = [];
collection.distinct('make.name', (err, docs) => {
data.push({'make': docs });
});
collection.distinct('model', (function (err, docs) {
data.push({'model': docs });
}))
res.send(data);
});
由于NodeJS / Express是异步的,因此无法正常运行。 如何重构此端点以进行多个数据库调用(来自同一集合)并返回包含该端点的对象?
有多种方法可以做到这一点:
没有承诺,您可以嵌套回调:
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
但这可能仍然不是最方便的方法。
async
/ await
如果您要打30次电话,最灵活的方法是:
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
关键字创建的函数中使用它。 有关更多信息,请参见:
有关浏览器的支持,请参阅:
有关Node的支持,请参见:
在您没有本地支持async
并await
,可以使用Babel:
或使用稍有不同的语法,使用基于生成器的方法(例如co
或Bluebird协程):
查看这些答案以获取更多信息:
您可以用Promises做到
router.post('/search', (req, res) => {
var collection = db.get().collection('styles');
// Create promise for "make.name" query
let firstQuery = new Promise((resolve, reject) => {
collection.distinct('make.name', (err, docs) => {
if (!err) {
resolve(docs);
} else {
reject(err);
}
});
});
// Create promise for "model" query
let secondQuery = new Promise((resolve, reject) => {
collection.distinct('model', (function (err, docs) {
if (!err) {
resolve(docs);
} else {
reject(err);
}
}))
})
// Run both queries at the same time and handle both resolve results or first reject
Promise.all([firstQuery, secondQuery])
.then((results) => {
res.send({ "make.name": results[0], "model": results[1] });
})
.catch((err) => {
// Catch error
res.send({});
});
});
您也可以在回调函数中使用解构,例如:
Promise.all([firstQuery, secondQuery])
.then(([makeName, model]) => res.send({ "make.name": makeName, model }))
UPD:例如,如果您有大量要请求的集合,则可以创建一个集合名称数组,将其映射为Promise.all来承诺请求并进行处理。
let collections = ["firstCollection", "secondCollection", "nCollection"];
let promises = collections.map((collectionName) => {
return new Promise((resolve, reject) => {
collection.distinct(collectionName, (err, docs) => {
if (!err) {
resolve(docs)
} else {
reject(err);
}
});
})
});
Promise.all(promises)
.then(results => {
// Do what you want to do
})
.catch(error => {
// or catch
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.