2017-09-27 59 views
0

我是nodeJs的新手。在for循环中,从某个url获取数据后,我得到未定义的数组[i]值。我不知道如何解决这个问题。请帮帮我。为什么我得到for循环的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:''}) 
    } 
}) 
} 
+1

将'var i'更改为'let i'为词法范围。为了理解你的问题,也可以在有问题的位置尝试'console.log(i)'。 –

+0

'urls [i] .url' is undefined –

+0

@PatrickRoberts当然你是对的。我的错误 – hammus

回答

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的价值,即使在异步函数,所以变量引用不会被之前迭代的for循环覆盖。

你的第二个选择是使用let像这样引入ES6词法作用域变量声明:

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: '' 
     }) 
    } 
    }) 
}) 

词法作用域意味着for循环的块范围内的任何参考i,即使在异步函数的主体,将参考那个for循环的特定迭代,从而允许它看起来像它应该那样工作。

+0

是的,它的工作正常。非常感谢你 – siva

0

Patrick很好的回答。我想补充几点。

要回答这个问题,你为什么在console.log(urls[i])越来越undefined因为i的值是4,没有出现在索引4

现在到了为什么我是4. request是一个异步调用,并且一旦你调用request.get,它通过事件循环,并被写入堆栈(与正确的URL)被调用。 。只有在当前呼叫结束后,才会调用此堆栈,这是在for循环结束之后。只有当我是4时,你的循环才会结束并且var是全局范围

以下是一个great video以了解事件循环如何工作。

+0

哦,我认为这将是一个范围问题:'我'不应该存在于循环外,所以它不应该存在于请求的'console.log()' – mJehanno

+0

如果我运行这个 ''' const request = require('request'); const urls = ['http://www.google.com','http://bing.com','https://duckduckgo.com']; 为(VAR I = 0; I AbhinavD

相关问题