通过mongoose访问数组元素

时间:2016-04-20 10:49:46

标签: javascript node.js mongodb mongoose

有了这份文件:

{
    "_id" : 8,
    "updatedAt" : ISODate("2016-04-13T05:07:38.905Z"),
    "createdAt" : ISODate("2016-04-13T04:15:37.612Z"),
    "author" : "test@test.com",
    "urgency" : "slow",
    "state" : "pending",
    "comment" : "",
    "requests" : [
        {
            "value" : 1,
            "product" : "Slethoxynal",
            "_id" : ObjectId("570dc7e91d15852f1c2ae66a")
        },
        {
            "value" : 1,
            "product" : "Thyrploxynénol",
            "_id" : ObjectId("570dc7e91d15852f1c2ae66b")
        }
    ],
    "__v" : 0
}

我使用这个javascript函数:

function closeRequest(req, res, next) {
    Request.findOne({ '_id': req.body.id}, function(err, request){
        debug(request);
        debug("Length is %s", request.requests.length);
        for(var i=0;i<request.requests.length;i++){
            debug("We validate the element %s of the request %s", i, req.body.id);
            console.log(i);
            Material.findOne({'title': request.requests[i].product}).exec(function(err, material){
            debug("Inside i is : %i",i);
            debug("Product is %s", request.requests[i].product);
            debug("Material found is %s", material.title);
            material.amount -= request.requests[i].value;
            material.save(function(err) {
            if(err)
                res.send(err);
            });
        });
        }
        request.state='accepted';
        request.save(function(err) {
            if(err)
                res.send(err);
        });
    });

    res.redirect('back');
  }

我的控制台打印出来:

0
1
Inside i is 2

然后该功能崩溃

TypeError: Cannot read property 'product' of undefined

在第

debug("Product is %s", request.requests[i].product);

此功能的目标是验证一个请求(我们将其状态从&#39;等待&#39;接受&#39;接受&#39;)。但是,当我们这样做时,仓库中的库存需要递减(&#39;金额&#39;参数)。 我们无法访问产品属性似乎很合乎逻辑,因为i的值为2且数组中没有第三个元素。 但为什么我的迭代变量超出了它的范围?我怎么解决这个问题?控制台打印&#34; Inside&#34;只有一次让我想知道它是不是另一个异步问题。

1 个答案:

答案 0 :(得分:1)

这是关于异步执行代码的问题。特别是for循环&#34;触发&#34;多个异步函数和连续执行。循环遍历循环i===2之后。当第一个Material.findOne回调被执行时requests[2] === undefined(如requests.length === 2)会引发您的错误。

我建议这样做:

var updateMaterialFns = request.requests.map(function(req, i) {
  return function(done) {
    debug("We validate the element %s of the request %s", i, req.body.id);
    console.log(i);
    Material.findOne({'title': req.product}).exec(function(err, material){
      if (err) {
        done(err)
      }
      debug("Inside i is : %i",i);
      debug("Product is %s", request.requests[i].product);
      debug("Material found is %s", material.title);
      material.amount -= request.requests[i].value;
      material.save(done)
    })
  }
})

async.parallel(updateMaterialFns, function(err) {
  if (err) {
    res.send(err)
  }
})

async是一个node / npm模块,具有许多处理异步编程执行和控制流程的函数。