2010-12-05 5 views
18

저는 경험이 풍부한 소프트웨어 개발자이지만 JS와 노드에 꽤 새로운 것입니다. 저는 슈퍼 중첩 코드에 대한 열렬한 팬이 아니므로 콜백을 자신의 함수로 분해하려고했습니다. 콜백이 발생할 때 범위를 유지하는 방법을 알아내는 데 문제가 있습니다. 주위를 파고 콜백을 통해 클로저를 만들면 작동 할 것이지만 예상대로 작동하지 않는 것으로 보입니다. 나는() 함수 폐쇄에 writeBody() 호출을 래핑하여 내가 범위를 가질 것이라고 생각node.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); 

:

여기에 나를 위해 작동하지 않는 코드의 종류의 매우 간단한 버전입니다 나는 타임 아웃 후 필요하지만

이 가

ReferenceError: res is not defined

사람이 내가 잘못하고있는 중이 야 boneheaded 무슨 일이 말해 줄 수 얻을 writeBody()가 화재 때?

답변

35

기본적으로 클로저가 작동하지 않는 함수는 외부 함수 범위를 상속받습니다.

// 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); 

은 그러나이 같은 것들을 조심해야합니다 참조가 동일하며 i10 모든 방법까지 증가됩니다 때문에

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 열 번 인쇄됩니다. 서로 다른 숫자를 가지려면 각각의 변수를 새로 만들 필요가 있습니다. 에 전달하는 익명 자체 함수에 setTimeout을 래핑하거나 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); 
} 
+0

오! 이런! * 페이스 팔먼 * 그게 도움이되는 톤, 난 그냥 내 머리에 shift - ey 순간을했다. – MahatmaManic

2

, 즉

http.createServer(function(req, res) 
{ 

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

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

나는 종종이 항상 범위에 유지하는 변수의 무리를 전달하는 것보다 쉽게 ​​찾을 수 있습니다, 당신은 또한 기능이 중첩 할 수 있습니다, 그래서 그들은 범위를 공유 이 함수를 다른 곳에서 재사용 할 수는 없습니다.

+1

시간을내어 주셔서 감사 드리며, 종종 쉽고 빠르다고 생각할 수도 있습니다. 그러나 스타일의 일반적인 규칙에 따라 할 수있는 곳을 중첩시키지 않으려 고 노력합니다. 이 간단한 예에서는 물론 그렇게 나쁘지는 않지만 일이 복잡해지면 (예 : 파일 찾기, 읽기 및 처리) 추악 해집니다. – MahatmaManic

+0

나는이 스타일을 선호합니다. 이 개념을 확장 한 답변을 게시했습니다. – rocketsarefast

0

당신은 너무 콜백에서 응답을 전달할 수 있습니다

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

나는 실제로 저스틴 코맥의 대답있다. 최근에 작성한 좀 더 극단적 인 예가 있습니다.

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 함수가 절름발이라는 것을 인정한다. 어느 쪽이든, 이것은 범위의 좋은 예입니다.

관련 문제