Javascript 如何维护node.js回调中的作用域?

Javascript 如何维护node.js回调中的作用域?,javascript,node.js,Javascript,Node.js,我是一名经验丰富的软件开发人员,但对JS和node来说都是新手。我不太喜欢超级嵌套代码,所以我一直在尝试将回调分解成它们自己的函数。不过,我在弄清楚如何在回调触发时维护作用域方面遇到了麻烦。我在书中读到,如果我在回调上创建了一个闭包,它会起作用,但它似乎不像我预期的那样起作用 下面是一个非常简单的代码版本,它不适合我: function writeBody() { res.end("<h1> Hooray! </h1>"); } http.createServe

我是一名经验丰富的软件开发人员,但对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()
{
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();
    })});
};