环回:对环回api进行同步呼叫
我想对使用环回设计的其中一个API进行同步呼叫。这里是我的代码:环回:对环回api进行同步呼叫
router.get('/friends', function(req, res, Array) {
var friendsList = []
for(var counter=0;counter<length;counter++){
Model.findById(Array[counter].Id,function(err, record) {
if(record){
friendsList.push(record);
}
});
}
res.status(200).json(friendsList);
});
现在即时得到前阵的响应,好友列表是越来越完全填充。我想让这个同步并得到正确的回应。我该怎么办?
谢谢!
一个简单的方法来做到这一点是
- 设置一个变量在每次回调被调用时
length
- ,由1
- 减少这个变量,当它达到零,你处理最终回调
- 在回调,调用
res.status...
筛选:
router.get('/friends', function(req, res, array) {
var friendsList = [];
var remaining = length;
for(var counter=0;counter<length;counter++){
Model.findById(array[counter].Id, function(err, record) {
if (record){
friendsList.push(record);
}
remaining -= 1;
if (remaining == 0) {
res.status(200).json(friendsList);
}
});
}
});
为了完整性......因为你正在使用...的NodeJS使用(本机)承诺与arrow function
语法
router.get('/friends', (req, res, array) =>
Promise.all(array.map(item =>
new Promise((resolve, reject) =>
Model.findById(item.Id, (err, record) =>
resolve(record || undefined)
)
)
))
.then(friendsList =>
res.status(200).json(friendsList.filter(item =>
item !== undefined
))
)
);
谢谢@Jaromanda,这真的有用。欣赏它。 –
承诺方式在节点v9.2.0中与我不同步 –
“承诺方式”在任何地方都不同步 - 承诺本质上是异步的。考虑到'Model.findById'已经是异步的,没有办法获得同步的结果 –
使用的承诺和$in
运营商猫鼬:
router.get('/friends', function(req, res, arr) {
var promise = Model.find({ _id: { $in: arr.slice(0, length).map(function (e) { return e.Id }) } }).exec()
promise.then(function (friendsList) {
res.status(200).json(friendsList)
})
})
arr.slice
挑选数组中的第一个length
元素。 Model.find
创建单个查询,这比执行多个findById
查询更有效。 $in
运算符接受一个ID数组来进行查找。 .exec()
创建一个单一的承诺,这是与.then(...)
解决。
Model.find如何知道在每个数组项目中查找“Id”?应该有地图吗?另外,是什么让你认为猫鼬参与?(并不是说你错了,只是在发布答案之前看不到任何提及) –
'$ in'运算符接受一个id数组。由于使用的语法,我假定了Mongoose。但是,大多数现代ORM支持多种对象查找和承诺的概念。对于Mongoose以外的ORM,可以使用适当的API调用。 –
你错过了我的问题。原始代码表明'array'是一个'object'数组,它具有一个属性'Id' - 你的代码似乎没有传递一个Id数组,它传递的是原始对象数组的一个副本 –
我会使用async
和underscore
模块
var async = require('async');
var _ = require('underscore');
router.get('/friends', function(req, res, Array) {
var friendsList = [];
var waterfallFunctions = [];
_.each(Array, function(element) {
waterfallFunctions.push(function(next) {
Model.findById(element.Id,function(err, record) {
if (err) return next(err);
if(record){
friendsList.push(record);
}
next();
});
});
});
//async waterfall calls the functions in the array in order.
async.waterfall(waterfallFunctions, function (err) {
if (err) return res.status(500);
res.status(200).json(friendsList);
});
});
你应该等待,直到N findById调用完成这样的解决方案是做出承诺的数组,并使用Promise.all方法。
router.get('/friends', function(req, res, Array) {
var friendsList = []
var friendsPromises = []
for (var counter=0; counter<length; counter++) {
var friend = Model.findById(Array[counter].Id;
friendsList.push(friend)
friend.then(function(record) {
if (record) {
friendsList.push(record);
}
})
}
Promise.all(friendsPromises).then(function(){
res.status(200).json(friendsList);
})
});
您无法对异步函数进行同步调用 –
将res.json放在回调函数中? – tymeJV
@tymeJV - 这不会工作,因为回调可能是(可能是如果你看代码)多次调用 –