繁体   English   中英

在现有对象中添加新元素

[英]Add new element in existing object

我正在使用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);
});

我想将user.getUserInfo中的元素“ foo”添加到user.getMatch返回的对象“ match”中。 然后将所有数据发送给客户端。

但是它出错了,因为user.getUserInfo内部的“ k”不等于外部的“ k”。 我不知道为什么两个“ k”不相等。

以及执行循环后如何将响应发送给客户端。

谢谢你的帮助!

这里有些问题:

首先,没有定义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来实现,每次获得用户信息时该变量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 });
    }
  });
});

当您说“ k inside and outside”时,是指在user.getUserInfo(function(err2,info){})的内部还是外部?
我不确定您的情况,但是我可以想到两件事

  1. 由于函数“ function(err2,info)”是一个回调,并且是异步执行的,因此在getUserInfo中使用k的上下文/堆栈完全不同。 所以尝试在调用ie时传递k

    user.getUserInfo(function(err2,info,k){})。 这应该工作

  2. 尝试在要使用的闭包中声明k即var k



更新问题的另一部分
“但是还有另一个问题。在添加“ foo”元素之前,它先向客户端发送响应。因此,在对客户端的响应中,它仅从“ match”对象发送,而没有“ foo”元素。”
这又是因为获取用户信息的内部代码是异步执行的。 为此,您需要保留一个全局标志或尝试从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);
                     }

            });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM