我正在使用node.js。
我必须在对象中添加新元素才能向客户端发送响应。
user.getMatch(req.user, function(err, match){
for( k=0; k<match.length; k++){
var userId = {
id : match[k].match_id
};
var user = new User(userId);
console.log('k: ' + k);
user.getUserInfo(function(err2, info){
console.log('k here: ' + k);
if(info){
match[k].foo = info[0].foo;
}
});
}
var response = {
data : match
};
res.json(response);
});
我想添加一个元素&#34; foo&#34;从user.getUserInfo到对象&#34;匹配&#34; user.getMatch返回的内容。然后将所有数据作为响应发送给客户端。
但它有一个错误,因为&#34; k&#34; user.getUserInfo里面不等于&#34; k&#34;外。 我不知道为什么这两个&#34; k&#34;不平等。
如何在执行循环后向客户端发送响应。
感谢您的帮助!
答案 0 :(得分:1)
这里有一些问题:
首先,k未定义,因此您使用的k实际上是一个不是您想要的全局变量。您需要将其定义为'var k'。
其次,您传递给user.getUserInfo()
的回调函数(可能)将来会在某个未知时间执行。此时,您的循环for (k ...
已经完成,因此k
变量已经具有一个新值,因为它在您调用user.getUserInfo()
时具有的值。这里是棘手的部分:回调函数中的代码将使用k的最新值。它将不使用k创建函数时的值。
您可以通过向回调函数添加参数并使用.bind
方法将k绑定到它来解决此问题:
user.getMatch(req.user, function(err, match){
var k;
for(k=0; k < match.length; k++){
var userId = {
id : match[k].match_id
};
var user = new User(userId);
console.log('k: ' + k);
var callback = function(k, err2, info){
console.log('k here: ' + k);
if(info){
match[k].foo = info[0].foo;
}
}.bind(null, k);
user.getUserInfo(callback);
}
var response = {
data: match
};
res.json(response);
});
另外,使用.forEach
迭代数组会更好:
user.getMatch(req.user, function(err, match){
match.forEach(function(curr) {
var userId = {
id : curr.match_id
};
var user = new User(userId);
user.getUserInfo(function(err2, info){
if(info){
curr.foo = info[0].foo;
}
}
});
var response = {
data: match
};
res.json(response);
});
虽然Array.forEach可以在迭代中为您提供当前索引,但不再需要这样。只需使用curr
值(它为您提供迭代中的当前元素)。
最后,我认为此处的代码可能会在执行所有user.getUserInfo()
调用之前发送响应。要实现这一点,您需要知道所有user.getUserInfo()
何时完成。这可以通过添加变量numLeft
来实现,该变量在每次获取用户信息时递减。当此变量达到零时,我们知道所有getUserInfo()
都已完成,因此可以安全地发回响应。
user.getMatch(req.user, function(err, match) {
var numLeft = match.length;
match.forEach(function(curr) {
var user = new User({
id : curr.match_id
});
user.getUserInfo(function(err2, info){
if(info) {
curr.foo = info[0].foo;
}
--numLeft;
if (numLeft == 0)
res.json({ data: match });
}
});
});
答案 1 :(得分:0)
当你说&#34; k内外&#34;你的意思是在user.getUserInfo内部和外部(函数(err2,info){})?
我不确定你的背景,但我可以想到两件事
由于功能&#34;功能(错误2,信息)&#34;是一个回调,并且异步执行getUserInfo中使用k的上下文/堆栈是完全不同的。所以尝试在呼叫时传递k,即
user.getUserInfo(function(err2,info,k){})。这应该有用
尝试在要使用它的闭包中声明k即var k
更新另一部分问题
&#34;但是我又遇到了另一个问题..它在添加&#34; foo&#34;之前向客户发送回复。元件。所以在对客户端的响应中,它只发送来自&#34; match&#34;没有&#34; foo&#34;元素&#34。
这也是因为你的内部获取用户信息的ur代码是异步执行的。
为此,您需要保留全局标志或尝试从getUserInfo中发送响应
即。
var mathLen = match.length;
user.getUserInfo(function(err2, info,k,mathLen)
{
console.log('k here: ' + k);
if(info){
match[k].foo = info[0].foo;
}
if(k==mathLen)
{
var response = {
data : match
};
res.json(response);
}
});