\**
* user.petIds = ["1","2","3","4"];
*\
getPets: function(users){
var response = [];
users.forEach(function(user){
Pet.find(users[i].petIds).exec(function(err, pets){
if(err) return null;
console.log("index: "+i);
response.push({ name: users[i].name, pets: pets});
});
});
return response;
}
我希望为一系列用户从一系列宠物ID中获取所有宠物。但是,exec仅在回调之后执行,在这种情况下会导致返回过早。 Sails中有什么可以解决这个问题吗?否则,无法使用for循环进行查询。我对JS的工作方式还很新。任何帮助表示赞赏。谢谢(:
答案 0 :(得分:2)
这不是一个Sails问题,它是Node的一个普遍问题,当您了解有关异步编程的更多信息时,您会遇到它。如果你在" node.js中搜索StackOverflow异步循环"你会找到dozens of questions and answers。问题是您在同步.exec()
循环内调用异步函数(for
),因此循环的所有迭代(以及return response
)都在任何循环之前发生调用实际的回调(function(err, pets)
函数)。
解决此问题的最简单方法是使用像async
这样的库来异步运行循环。由于这个原因,默认情况下Sails包含并全局化async
,所以你可以这样做:
// Note the new second argument to "getPets", since this is
// an asynchronous function it requires a callback
getPets: function(users, getPetsCb){
// Asynchronous "map" call to transform users
async.map(users, function iterator (user, mapCb){
// Get the user's pets
Pet.find(user.petIds).exec(function(err, pets) {
// In case of error pass it to the callback, which
// will abort the loop
if(err) return mapCb(err);
// Use "null" as the first arg to indicate no error has
// occurred, and pass the transformed user as the second
// to add it to the array
return mapCb(null, { name: user.name, pets: pets});
});
},
// Pass the outer callback as the 3rd argument to async.map
// to pass the final error state and array of transformed
// users to whoever called "getPets"
getPetsCb);
}
阅读full docs for async.map
here以及所有其他有趣的async
方法。
另请注意,在您的特定情况下,您可以使用Sails associations对User和Pet之间的关系进行建模,并使用一个查询获取所有这些信息:User.find(...).populate('pets').exec(...)
!
答案 1 :(得分:2)
如果您使用Sails .10或更高版本,您可以使用模型关联来解决问题,方法略有不同。事实上,他们在documentation中详述了一个非常相似的用例。
如果您以这种方式设置模型:
对myApp / API /模型/ pet.js
module.exports = {
attributes: {
name:'STRING',
// include whatever other attributes
owner:{
model:'user'
}
}
}
对myApp / API /模型/ user.js的
module.exports = {
attributes: {
name:'STRING',
// other attributes you may want included here
pets:{
collection: 'pet',
via: 'owner'
}
}
}
然后在您的控制器中,您可以使用以下内容查找给定用户的所有宠物:
getPets: function(req, res) {
User.find()
.where({id: users})
.populate('pets')
.exec(function(err, users) {
if (err) throw err; // do error handling here
return res.json({
users: users
});
});
}
通过执行此操作,发送回给您的JSON包含每个用户以及此处所示的所有用户的宠物。
{
users:
[{
pets:
[ { name: 'Spot',
id: 2,
createdAt: Tue Feb 11 2014 17:58:04 GMT-0600 (CST),
updatedAt: Tue Feb 11 2014 17:58:04 GMT-0600 (CST),
owner: 1 },
{ name: 'Sparky',
id: 4,
createdAt: Tue Feb 11 2014 18:02:58 GMT-0600 (CST),
updatedAt: Tue Feb 11 2014 18:02:58 GMT-0600 (CST),
owner: 1 } ],
name: 'Mike',
createdAt: Tue Feb 11 2014 17:49:04 GMT-0600 (CST),
updatedAt: Tue Feb 11 2014 17:49:04 GMT-0600 (CST),
id: 1
}]
}
然后,您可以使用返回的JSON访问单个用户的宠物。