Loopback : 同步调用 loopback api
Loopback : Making synchronous call to loopback 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);
});
现在我在数组之前收到响应,friendList 已完全填充。我想让这个同步并得到正确的响应。我该怎么办?
谢谢!
一个简单的方法是
- 设置一个变量为
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...使用(本机)Promise 和 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
))
)
);
在 Mongoose 中使用 Promises 和 $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(...)
解决。
我会使用 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);
})
});
我想对我使用回送设计的 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);
});
现在我在数组之前收到响应,friendList 已完全填充。我想让这个同步并得到正确的响应。我该怎么办?
谢谢!
一个简单的方法是
- 设置一个变量为
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...使用(本机)Promise 和 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
))
)
);
在 Mongoose 中使用 Promises 和 $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(...)
解决。
我会使用 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);
})
});