我是一名经验丰富的软件开发人员,但对于JS和node来说,我还是个新手。我不是超级嵌套代码的狂热爱好者,所以我一直在尝试将回调分解到它们自己的函数中。不过,我在弄清楚如何在回调触发时维护作用域时遇到了问题。深入研究后,我读到如果我在回调上创建一个闭包,它将会工作,但它似乎不会以我预期的方式工作。
这是一个非常简单的代码版本,它对我来说不起作用:
function writeBody()
{
res.end("<h1> Hooray! </h1>");
}
http.createServer(function(req, res)
{
res.writeHead('Content-Type', 'text/html');
setTimeout(function(){writeBody()}, 2000);
}).listen(8000);
我以为通过将writeBody()调用包装在function()闭包中,我就可以在超时后获得所需的作用域,但是当writeBody()触发时,我得到
ReferenceError:未定义res
谁能告诉我我做错了什么愚蠢的事情?
发布于 2010-12-05 16:09:54
基本上不是闭包是如何工作的,函数继承了它们的外部作用域,这就是它的工作方式。
// this function only inherits the global scope
function writeBody()
{
res.end("<h1> Hooray! </h1>");
}
http.createServer(function(req, res) // a new local varaible res is created here for each callback
{
res.writeHead('Content-Type', 'text/html');
// annonymous function inheris both the global scope
// as well as the scope of the server callback
setTimeout(function(){
// the local variable res is available here too
writeBody()
}, 2000);
}).listen(8000);
要使其工作,只需将res
对象传递到函数中,因为它在超时回调中可用。
function writeBody(res)
{
// NOT the same variable res, but it holds the same value
res.end("<h1> Hooray! </h1>");
}
http.createServer(function(req, res)
{
res.writeHead('Content-Type', 'text/html');
setTimeout(function(){
writeBody(res); // just pass res
}, 2000);
}).listen(8000);
但是你需要注意这样的事情:
for(var i = 0; i < 10; i++) { // only one i gets created here!()
setTimeout(function() {
console.log(i); // this always references the same variable i
}, 1000);
}
这将打印10
十次,因为引用是相同的,并且i
会一直递增到10
。如果你想拥有不同的数字,你需要为每个数字创建一个新的变量,方法是将setTimeout
封装到匿名的self函数中,并将其作为参数传递给i
,或者调用一些其他方法来设置timouet并将i
作为参数接收。
// anoynmous function version
for(var i = 0; i < 10; i++) {
(function(e){ // creates a new variable e for each call
setTimeout(function() {
console.log(e);
}, 1000);
})(i); // pass in the value of i
}
// function call version
for(var i = 0; i < 10; i++) {
createTimeoutFunction(i);
}
发布于 2010-12-09 19:08:32
您还可以使函数嵌套,以便它们共享作用域,即
http.createServer(function(req, res)
{
function writeBody()
{
res.end("<h1> Hooray! </h1>");
}
res.writeHead('Content-Type', 'text/html');
setTimeout(function(){writeBody()}, 2000);
}).listen(8000);
我经常发现这比总是传递一堆变量来保持作用域更容易,尽管这意味着你不能在其他地方重用函数。
发布于 2012-08-17 04:25:34
你可以在你的回调中传递响应,这样:
http.createServer(function(req, res)
{
res.writeHead('Content-Type', 'text/html');
setTimeout(function(){writeBody(res)}, 2000);
}).listen(8000);
https://stackoverflow.com/questions/4357881
复制相似问题