Javascript 如何维护node.js回调中的作用域?
我是一名经验丰富的软件开发人员,但对JS和node来说都是新手。我不太喜欢超级嵌套代码,所以我一直在尝试将回调分解成它们自己的函数。不过,我在弄清楚如何在回调触发时维护作用域方面遇到了麻烦。我在书中读到,如果我在回调上创建了一个闭包,它会起作用,但它似乎不像我预期的那样起作用 下面是一个非常简单的代码版本,它不适合我:Javascript 如何维护node.js回调中的作用域?,javascript,node.js,Javascript,Node.js,我是一名经验丰富的软件开发人员,但对JS和node来说都是新手。我不太喜欢超级嵌套代码,所以我一直在尝试将回调分解成它们自己的函数。不过,我在弄清楚如何在回调触发时维护作用域方面遇到了麻烦。我在书中读到,如果我在回调上创建了一个闭包,它会起作用,但它似乎不像我预期的那样起作用 下面是一个非常简单的代码版本,它不适合我: function writeBody() { res.end("<h1> Hooray! </h1>"); } http.createServe
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()
{
res.end(“万岁!”);
}
http.createServer(函数(req,res)
{
res.writeHead('Content-Type','text/html');
setTimeout(函数(){writeBody()},2000);
}).听(8000);
我认为通过将writeBody()调用包装到function()闭包中,可以在超时后获得所需的作用域,但是当writeBody()激发时,我得到了
ReferenceError:未定义res
有人能告诉我我做错了什么吗?基本上,闭包不是如何工作的,函数继承了它们的外部作用域,这就是它的工作方式
// 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);
但你需要注意这样的事情:
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);
}
您还可以嵌套函数,以便它们共享作用域,即
http.createServer(function(req, res)
{
function writeBody()
{
res.end("<h1> Hooray! </h1>");
}
res.writeHead('Content-Type', 'text/html');
setTimeout(function(){writeBody()}, 2000);
}).listen(8000);
http.createServer(函数(req,res)
{
函数writeBody()
{
res.end(“万岁!”);
}
res.writeHead('Content-Type','text/html');
setTimeout(函数(){writeBody()},2000);
}).听(8000);
我经常发现这比总是传递一组变量来保持作用域更容易,尽管这意味着您不能在其他地方重用该函数。您可以在回调中传递响应,以便:
http.createServer(function(req, res)
{
res.writeHead('Content-Type', 'text/html');
setTimeout(function(){writeBody(res)}, 2000);
}).listen(8000);
我真的很喜欢贾斯汀·科马克的答案。这是我最近的一些编码的一个更极端的例子
var Func4 = function(req, res)
{
var collectionName = "parts";
var f0 = function() {mongodbClient.collection(collectionName, f1);};
var f1 = function(err, coll) {coll.ensureIndex("item", f2);};
var f2 = function(err, indexname)
{
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write("index name = " + indexname);
res.end();
};
f0();
};
大多数人都会告诉我(他们确实这样做了),这是编写代码的正确方法
var Func4 = function(req, res)
{
var collectionName = "parts";
mongodbClient.collection(collectionName, function(err, coll) {
coll.ensureIndex("item", function(err, indexname) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write("index name = " + indexname);
res.end();
})});
};
也许我是n00b,但我发现嵌套回调有点难以遵循。我也承认一堆f0,f1,f2函数是蹩脚的。不管怎样,这都是一个很好的范围示例。哦!哼!facepalm帮了我很多忙,我的脑子里刚刚有了一个转变。我感谢你花时间回答,你可能是对的,它通常更快、更容易,但作为一种风格的一般规则,我尽量避免在我能做的地方筑巢。在这个简单的例子中,当然没那么糟糕,但是当事情变得越来越复杂(比如查找、读取和处理文件)时,它会很快变得难看。我更喜欢这种风格。发布了一个关于这个概念的答案。
var Func4 = function(req, res)
{
var collectionName = "parts";
var f0 = function() {mongodbClient.collection(collectionName, f1);};
var f1 = function(err, coll) {coll.ensureIndex("item", f2);};
var f2 = function(err, indexname)
{
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write("index name = " + indexname);
res.end();
};
f0();
};
var Func4 = function(req, res)
{
var collectionName = "parts";
mongodbClient.collection(collectionName, function(err, coll) {
coll.ensureIndex("item", function(err, indexname) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write("index name = " + indexname);
res.end();
})});
};