node js:for循环中的-null值错误

时间:2015-07-02 06:02:14

标签: javascript arrays json node.js callback

您好我是nodejs的新手我正在尝试实现一个项目,我们必须在该项目中使用事件管理站点。我们正在为特定用户向页面添加事件。

现在问题是我现在陷入困境: -

   exports.getDashBoard=function(req,res){
    var eventList=[];
       for(var i=0;i<req.user.invites.length;i++)
       {
                   Event.find({_id:req.user.invites[i]},function(err,events){
                   if(err)
                   {
                   console.log(err);  
                   }
                   else
                   {
                    eventList.push(events[0]);
                    console.log(eventList);
                    // shows value inside the array as wanted
                   }
                 });
       }
    console.log(eventList);
                // shows null value why? the variable is in the scope as its declaration 

   res.render('dashboard');
   };

说明: 我创建了一个函数,其中每次调用函数时都声明并初始化变量eventList。我在内部函数中使用了这个变量eventList来更新它的值并连接到以前的值.. console.log显示eventList正在按需要更新。但是当我尝试在内部函数之外使用这个变量时,doenst工作,我得到一个空数组初始化变量的范围是本地是在主函数中,并在内部函数内可见,但当我在内部函数后使用它,即在for循环外,数组显示空值 怎么办?

下图: - 我创建了一个函数,其中每次调用函数时都声明并初始化变量eventList。我在内部函数中使用了这个变量eventList来更新它的值并连接到previoys值.console.log显示eventList正在按需要更新。但是当我尝试在内部函数之外使用这个变量时,doenst工作,我得到一个空数组初始化变量的范围是本地是在主函数中,并在内部函数内可见,但当我在内部函数后使用它消失

怎么办?

enter image description here

3 个答案:

答案 0 :(得分:0)

您在实际填充之前打印eventList。当您执行外部eventList时,您正在将Event.find回调中的项目附加到可能尚未执行的console.log(eventList);回调中。

编辑:
要在调用所有回调后打印集合,您可以在最后一次迭代中检入回调,如果是,则打印eventList

if(i===(req.user.invites.length-1)){
    console.log(eventList);
}

您可以/也应该考虑更详细的内容async.js或某些承诺库(Q)。 使用async.js,您的代码看起来像(未经过测试):

async.eachSeries(req.user.invites, function (invite, callback) {
  Event.find({_id:invite}, function(err,events){
    if(err) {
      console.log(err);
      throw err;   
    } else {
      eventList.push(events[0]);
      console.log(eventList);
    }
  }
}, function (err) { // called once all iteration callbacks have returned (or an error was thrown)
  if (err) { throw err; }
  console.log(eventList); // Final version of eventList
});

答案 1 :(得分:0)

在循环结束之前调用Console.log。

您可以在内部函数中检查最后一个循环,并在true时调用:

if(err)
{

    console.log(err);  
}
else
{

    eventList.push(events[0]);
    console.log(eventList);
    // shows value inside the array as wanted

// Check if its the last loop, if so, print eventList
if(i==(req.user.invites.length-1)){

    console.log(eventList);
}

}

答案 2 :(得分:0)

  

显示空值为什么?变量在范围内作为其声明

for(var i=0;i<req.user.invites.length;i++)
       {
   // time taking task. probably db call.         
}
console.log(eventList); 

这是因为js是异步的。

在for循环中,它们存在一个耗时的任务,因此一旦for循环迭代结束,js指针将移动到下一行(console.log)。注意:只有迭代结束,但任务仍在进行中,稍后当这些任务完成时,将调用它们的回调。

模拟:

function(){
    for(var i =0;i<5;i++){
        setTimeout(function(){
            console.log('time taking task is over now.');
        }, 100);
    }
    console.log('I am after for loop');
}

这里输出如下:

I am after for loop
time taking task is over now.
time taking task is over now.
time taking task is over now.
time taking task is over now.
time taking task is over now.

简而言之,您需要通过确定哪些任务是耗时的任务以及哪些任务依赖于它们来管理您的工作流程。将所有这些依赖任务放在任务的回调中(这种方法虽然解决了问题,但随着需求的扩展,这会引发Callback hell / pyramid of doom的新问题。请参阅promises以了解即将到来的问题回调地狱)。

此外,您可以使用async等工作流程管理库,它将为您管理工作流程。