为什么我得到for循环的数组[i]值是未定义的

时间:2017-09-27 06:45:41

标签: node.js express

我是nodeJs的新手。在for循环中,我从一些url获取数据后得到array [i]值undefined。我不知道如何解决这个问题。请帮我。

这是我的代码

urls =['url1','url2','url3','url4']
 for (var i = 0; i < urls.length; i++) {
  console.log(urls[i]) // getting value
  var opt = {
    url :urls[i],
      headers: {
     'Authorization': 'Bearer '+reply
    } 
   }
  request.get(opt,function(error,response,body) {
     console.log(urls[i]) // getting undefined
     if(!error) {
        enrichment_data.push({type:body});
     } else {
     enrichment_data.push({type:''})
   }
 })
}

2 个答案:

答案 0 :(得分:4)

根据MDN,理解JavaScript闭包的这种逻辑错误是a common mistake

有两种实用的方法可以解决这个问题。仅使用ES5,解决此问题的最常规方法是使用urls.forEach()代替:

var urls = ['url1', 'url2', 'url3', 'url4']

urls.forEach(function(url, i) {
  console.log(urls[i]) // getting value
  var opt = {
    url: urls[i],
    headers: {
      'Authorization': 'Bearer ' + reply
    }
  }
  request.get(opt, function(error, response, body) {
    console.log(urls[i]) // getting undefined
    if (!error) {
      enrichment_data.push({
        type: body
      });
    } else {
      enrichment_data.push({
        type: ''
      })
    }
  })
})

使用此方法,您可以创建一个新的函数作用域,即使在异步函数中也可以保留每个i的值,这样变量引用就不会被{{的后续迭代所覆盖。 1}}你之前的循环。

您的第二个选择是使用let引入ES6词法范围变量声明,如下所示:

for

词法范围意味着在for循环的块范围内对var urls = ['url1', 'url2', 'url3', 'url4'] for (let i = 0; i < urls.length; i++) { console.log(urls[i]) // getting value var opt = { url: urls[i], headers: { 'Authorization': 'Bearer ' + reply } } request.get(opt, function(error, response, body) { console.log(urls[i]) // getting undefined if (!error) { enrichment_data.push({ type: body }); } else { enrichment_data.push({ type: '' }) } }) }) 的任何引用,即使在异步函数的主体内,也会引用特定的迭代i循环的em>,允许它按照它应该的样子运行。

答案 1 :(得分:0)

Patrick的精彩回答。我想补充几点。

要回答这个问题,为什么您在undefined获得console.log(urls[i]),因为i的值为4且索引为4时没有任何内容。

现在为什么我是4. request是一个异步调用,一旦你调用request.get,它就会经历事件循环并被写入堆栈(使用正确的URL)调用。 。只有在当前调用结束时才会调用此堆栈,即在for循环结束后。只有在i为4且var为全局范围

时,您的循环才会结束

以下是了解事件循环如何工作的great video