我怎样才能保持在node.jscallback的范围?

我是一名经验丰富的软件开发人员,但是对于JS和Node来说却是相当新的。 我不是超级嵌套代码的忠实粉丝,所以我一直试图将callback分解成自己的function。 在callback触发的时候,如何确定如何维持范围,我遇到了麻烦。 挖掘周围我读到,如果我在callback上创build了一个闭包它将工作,但它似乎并没有按照我预期的方式工作。

这是一个非常简单的代码,不适合我:

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()调用,我将有超时后我需要的范围,但是当writeBody()触发我得到

ReferenceError:res没有定义

任何人都可以告诉我,我做错了什么?

基本上,不是闭包是如何工作的,函数inheritance它们的外部作用域。

 // 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对象到函数中,因为它在超时callback中可用。

 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 。 如果你想拥有不同的数字,你需要为每个variables创build一个新的variables,或者把setTimeout包装成一个匿名的自我函数,这个函数可以作为一个parameter passing给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); } 

你也可以使function嵌套,所以他们共享范围,即

 http.createServer(function(req, res) { function writeBody() { res.end("<h1> Hooray! </h1>"); } res.writeHead('Content-Type', 'text/html'); setTimeout(function(){writeBody()}, 2000); }).listen(8000); 

我经常发现这比总是传递一堆variables来保持范围更容易,尽pipe这意味着你不能在别处重用函数。

你可以在你的callback中传递回应,所以:

 http.createServer(function(req, res) { res.writeHead('Content-Type', 'text/html'); setTimeout(function(){writeBody(res)}, 2000); }).listen(8000); 

我其实喜欢Justin Cormack的回答。 这是我最近编码的一个更极端的例子。

 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,但是我发现嵌套的callback有点难以遵循。 我也承认一堆f0,f1,f2的function是跛脚的。 无论哪种方式,这是范围的一个很好的例子。