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

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (74)

我对JS和节点非常陌生。我不太喜欢超级嵌套代码,所以我一直试图将回调分解到它们自己的函数中。但是,当回调触发时,我很难弄清楚如何维护范围。我仔细地看了看,如果我为回调创建了一个闭包,它就会起作用,但它似乎不像我预期的那样工作。

下面是一个非常简单的代码版本,它不适用于我:

function writeBody()
{
    res.end("<h1> Hooray! </h1>");
}

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

我认为,通过在函数()闭包中包装写eBody()调用,在超时之后我将拥有所需的范围,但是当writeBody()触发错误:

ReferenceError: res is not defined

提问于
用户回答回答于

闭包一般不怎么起作用,函数要继承它们的外部作用域:

// 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中传递的匿名自函数。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);
}
用户回答回答于

您还可以将函数嵌套,以便它们共享作用域,即

http.createServer(function(req, res)
{

    function writeBody()
    {
        res.end("<h1> Hooray! </h1>");
    }

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

扫码关注云+社区

领取腾讯云代金券