Node.js 在本地范围内保留全局变量的副本
Node.js keeps a copy of a global variable inside local scope
我有一个 Node.js 应用程序,它使用请求库来获取多个 URL。代码是这样的:
for(var i = 0; i < docs.length; i++){
var URL = docs[i].url;
request(URL, function(error, response, html){
console.log(URL);
// Other code...
}
为了简单起见,假设 docs
包含 URL,例如 [URL1、URL2、URL3、.. .]。在第一次迭代中,URL = URL1 并且向 URL 发送了一个请求。在第二次迭代中,请求被发送到 URL2 等等。然而,在循环结束时,URL = URLn。在事件完成函数中,当我记录 URL 时,我总是得到 URLn。但是,我需要能够获得相应的 URLs 即 [URL1, URL2, URL3, ...].
知道吗,我如何维护 URL 的本地副本,当全局 URL 发生更改时该副本保持不变?
这一定很简单,但我想不出来
只需将代码包装在函数中或使用 forEach。发生这种情况是因为闭包范围。
docs.forEach(functiom(doc) {
var URL = doc.url;
request(URL, function(error, response, html){
console.log(URL);
// Other code...
})
});
另一个修复
for(var i = 0; i < docs.length; i++){
makeRequest(docs[i]);
}
function makeRequest(doc) {
var URL = doc.url;
request(URL, function(error, response, html){
console.log(URL);
});
}
还有一个更丑陋的修复,在 for 循环中有一个闭包
for(var i = 0; i < docs.length; i++){
(function(doc) {
var URL = doc.url;
request(URL, function(error, response, html){
console.log(URL);
// Other code...
});
})(docs[i]);
}
如果你使用类似 JSHint 的东西,它会警告你不要在 for 循环中创建函数,因为它会导致这样的问题。
基本上,您在 JavaScript 中遇到的是正常行为,在 Node.js 中没有特殊行为。
JavaScript 中唯一定义作用域的是函数,函数可以访问它们自己的作用域以及任何 "outer" 作用域。
因此,解决方案是将您的代码包装在一个函数中,该函数将全局变量作为参数并将其作为参数提供给函数内的代码:每次调用该函数时都会对其进行评估,因此您的内部代码将获得自己的 "copy".
基本上你有两个选择。要么使用 立即执行的函数表达式 。这基本上只是一个无名(即匿名)函数,在定义的地方立即调用:
for(var i = 0; i < docs.length; i++){
(function (url) {
request(url, function(error, response, html){
console.log(url);
});
})(doc.url);
}
或者使用数组的内置 forEach
函数自动将其主体包装在函数中(产生相同的效果):
docs.forEach(function (url) {
request(url, function(error, response, html){
console.log(url);
});
});
您应该在 JavaScript here 中阅读闭包。
同时,简单来说,i
的值将在所有迭代结束时达到 n
。因此,你每次都会得到 URLn。如果将请求包装在一个立即调用的函数表达式中,那么您将在作用域链中创建另一个级别。通过这样做,请求方法的回调将不会在全局范围内引用变量 i
,而是在发送请求时在函数范围内可用的变量 i
.以及您期望的 i
的值。
代码会是这样的:
for(var i = 0; i < docs.length; i++){
var URL = docs[i].url;
(function(currentURL) {
//now the URL is preserved as currentURL inside the scope of the function
request(currentURL, function(error, response, html){
console.log(currentURL);
// This value of currentURL is the one that was available in the scope chain
// Other code...
});
})(URL);
}
只需使用 let
而不是 var
,即:
for(let i = 0; i < docs.length; i++){
let URL = docs[i].url;
request(URL, function(error, response, html){
console.log(URL);
//other code...
}
我有一个 Node.js 应用程序,它使用请求库来获取多个 URL。代码是这样的:
for(var i = 0; i < docs.length; i++){
var URL = docs[i].url;
request(URL, function(error, response, html){
console.log(URL);
// Other code...
}
为了简单起见,假设 docs
包含 URL,例如 [URL1、URL2、URL3、.. .]。在第一次迭代中,URL = URL1 并且向 URL 发送了一个请求。在第二次迭代中,请求被发送到 URL2 等等。然而,在循环结束时,URL = URLn。在事件完成函数中,当我记录 URL 时,我总是得到 URLn。但是,我需要能够获得相应的 URLs 即 [URL1, URL2, URL3, ...].
知道吗,我如何维护 URL 的本地副本,当全局 URL 发生更改时该副本保持不变?
这一定很简单,但我想不出来
只需将代码包装在函数中或使用 forEach。发生这种情况是因为闭包范围。
docs.forEach(functiom(doc) {
var URL = doc.url;
request(URL, function(error, response, html){
console.log(URL);
// Other code...
})
});
另一个修复
for(var i = 0; i < docs.length; i++){
makeRequest(docs[i]);
}
function makeRequest(doc) {
var URL = doc.url;
request(URL, function(error, response, html){
console.log(URL);
});
}
还有一个更丑陋的修复,在 for 循环中有一个闭包
for(var i = 0; i < docs.length; i++){
(function(doc) {
var URL = doc.url;
request(URL, function(error, response, html){
console.log(URL);
// Other code...
});
})(docs[i]);
}
如果你使用类似 JSHint 的东西,它会警告你不要在 for 循环中创建函数,因为它会导致这样的问题。
基本上,您在 JavaScript 中遇到的是正常行为,在 Node.js 中没有特殊行为。
JavaScript 中唯一定义作用域的是函数,函数可以访问它们自己的作用域以及任何 "outer" 作用域。
因此,解决方案是将您的代码包装在一个函数中,该函数将全局变量作为参数并将其作为参数提供给函数内的代码:每次调用该函数时都会对其进行评估,因此您的内部代码将获得自己的 "copy".
基本上你有两个选择。要么使用 立即执行的函数表达式 。这基本上只是一个无名(即匿名)函数,在定义的地方立即调用:
for(var i = 0; i < docs.length; i++){
(function (url) {
request(url, function(error, response, html){
console.log(url);
});
})(doc.url);
}
或者使用数组的内置 forEach
函数自动将其主体包装在函数中(产生相同的效果):
docs.forEach(function (url) {
request(url, function(error, response, html){
console.log(url);
});
});
您应该在 JavaScript here 中阅读闭包。
同时,简单来说,i
的值将在所有迭代结束时达到 n
。因此,你每次都会得到 URLn。如果将请求包装在一个立即调用的函数表达式中,那么您将在作用域链中创建另一个级别。通过这样做,请求方法的回调将不会在全局范围内引用变量 i
,而是在发送请求时在函数范围内可用的变量 i
.以及您期望的 i
的值。
代码会是这样的:
for(var i = 0; i < docs.length; i++){
var URL = docs[i].url;
(function(currentURL) {
//now the URL is preserved as currentURL inside the scope of the function
request(currentURL, function(error, response, html){
console.log(currentURL);
// This value of currentURL is the one that was available in the scope chain
// Other code...
});
})(URL);
}
只需使用 let
而不是 var
,即:
for(let i = 0; i < docs.length; i++){
let URL = docs[i].url;
request(URL, function(error, response, html){
console.log(URL);
//other code...
}