2014-04-28 11 views
40

Node.js의 콜백 함수에서 값을 반환 할 때 약간의 문제가 발생할 수 있으므로 가능한 한 쉽게 상황을 설명하려고 노력할 것입니다.Node.js의 콜백 함수에서 값 반환

urllib.request(urlToCall, { wd: 'nodejs' }, function (err, data, response) {        
    var statusCode = response.statusCode; 
    finalData = getResponseJson(statusCode, data.toString()); 
}); 

나는 함수 내부에 그것을 포장하고 같은 값을 반환하려고 : I 출력 URL을 소요하고 해당 URL을 안타 제공하는 스 니펫이 고려 때문에에

function doCall(urlToCall) { 
urllib.request(urlToCall, { wd: 'nodejs' }, function (err, data, response) {        
    var statusCode = response.statusCode; 
    finalData = getResponseJson(statusCode, data.toString()); 
    return finalData; 
}); 
} 

을 내 Node.js를 코드, 나는이 같은 urlToCall의 값이 결정됩니다 if-else 문을 많이 가지고 :

if(//somecondition) { 
    urlToCall = //Url1; 
} else if(//someother condition) { 
    urlToCall = //Url2; 
} else { 
    urlToCall = //Url3; 
} 

을 건 내부의 모든 문장이다 urllib.requesturlToCall의 값을 제외하고는 동일하게 유지됩니다. 그래서 확실히 공통 코드를 함수 안에 넣어야합니다. 나는 같은 것을 시도했지만 doCall은 항상 나를 undefined으로 돌려 보낼 것이다. 나는이 같은 시도 :

response = doCall(urlToCall); 
console.log(response) //Prints undefined 

을하지만 doCall() 내부 값을 인쇄하면 완벽하게 인쇄하지만 항상 undefined를 반환합니다. 내 연구에 따라 콜백 함수에서 값을 반환 할 수 없다는 것을 알게되었습니다. (사실입니까?) 그렇다면 모든 사람이이 상황을 처리하는 방법을 조언 해 줄 수 있습니다. 모든 if-else 블록에 중복 된 코드를 방지하고 싶습니다.

+0

"그것이 사실입니까?" - 맞아. –

+0

@ JanDvorak, 코드 복제 이외의 옵션이 없습니까? ;) –

+1

자신의 콜백 중 일부를 전달하면 도움이 될까요? 나는 그렇게 믿는다. –

답변

77

undefinedconsole.log(response)이 실행되기 전에 doCall(urlToCall);이 끝났기 때문입니다. 요청이 일 때 실행되는 콜백 함수도 전달해야합니다.

먼저, 귀하의 기능. 이제

function doCall(urlToCall, callback) { 
    urllib.request(urlToCall, { wd: 'nodejs' }, function (err, data, response) {        
     var statusCode = response.statusCode; 
     finalData = getResponseJson(statusCode, data.toString()); 
     return callback(finalData); 
    }); 
} 

: 그것을 콜백에 전달

var urlToCall = "http://myUrlToCall"; 
doCall(urlToCall, function(response){ 
    // Here you have access to your variable 
    console.log(response); 
}) 

@Rodrigo을 코멘트에 good resource을 기록했다. 노드의 콜백에 대한 내용과 작동 방식 비동기 코드임을 기억하십시오.

+0

+1 감사합니다, 당신의 예제는 좋아 보인다. 그것을 이해하고 실행하려고 노력할 것입니다. –

+4

이 작동합니다. 그러나 나는 질문이있다. doCall 함수를 호출했을 때. 어떻게 응답 변수를 반환 할 수 있습니까? 예를 들어 함수 밖에서 해당 변수를 가져 오려면? – Romeo

+0

@Romeo 같은 질문은 여기 !! – himanshupareek66

10

나는, 그것은 "반환"실제로 불가능하다 이것은 "작은 문제"아닙니다 Node.js를

에 콜백 함수에서 값을 반환에 기존에 값을 작은 문제에 직면하고있다 비동기 함수로부터의 감각.

"값을 반환 할 수 없으므로"값을 필요로하는 함수를 호출해야합니다. @display_name은 이미 귀하의 질문에 답변했지만 doCall의 반환 값이이 아닌 전통적인 방법으로 임을 지적하고 싶습니다. 당신은 다음과 doCall를 작성할 수

function doCall(urlToCall, callback) { 
    urllib.request(urlToCall, { wd: 'nodejs' }, function (err, data, response) {        
     var statusCode = response.statusCode; 
     finalData = getResponseJson(statusCode, data.toString()); 
     // call the function that needs the value 
     callback(finalData); 
     // we are done 
     return; 
    }); 
} 

라인 callback(finalData); 당신이 비동기 함수에서 얻은 값을 필요로하는 함수를 호출하는 것입니다.그러나 return 문은 함수가 여기을 종료 을 나타 내기 위해 사용된다는 것을 알고 있지만, 는 값이 호출자에 반환되는 것을 의미하지 않는다 (발신자가 이미 움직였다.)

2

당신이 원하는 경우, 너무 많이 수정하지 않고 코드를 작동시키는 것입니다. 당신이 콜백 문제없이 같은 목표를 달성하기 위해, 당신은 co을 사용할 수 있습니다 Node.js를를 사용 co-request되는 점을 감안

: 당신은 콜백 못된 및 가 동일한 코드 워크 플로우을 유지이 솔루션을 시도 할 수 있습니다.

기본적으로, 당신은 같은 것을 할 수 있습니다 : 다음

function doCall(urlToCall) { 
    return co(function *(){ 
    var response = yield urllib.request(urlToCall, { wd: 'nodejs' }); // This is co-request.        
    var statusCode = response.statusCode; 
    finalData = getResponseJson(statusCode, data.toString()); 
    return finalData; 
    }); 
} 

,

var response = yield doCall(urlToCall); // "yield" garuantees the callback finished. 
console.log(response) // The response will not be undefined anymore. 

를 이렇게함으로써, 우리는 콜백 함수가 완료 될 때까지, 다음의 값을 얻을 기다립니다. 여하튼, 그것은 당신의 문제를 해결합니다. - Node.js를위한

+0

하지만 이것은 ecma6 soultion –

+0

이며 성능에도 영향이 있습니다 –

+0

ecma6가 문제입니까? –

0

예제 코드 비동기 기능은 기능을 동기화하기 :

var deasync = require('deasync'); 

function syncFunc() 
{ 
    var ret = null; 
    asyncFunc(function(err, result){ 
     ret = {err : err, result : result} 
    }); 

    while((ret == null)) 
    { 
     deasync.runLoopOnce(); 
    } 

    return (ret.err || ret.result); 
} 
관련 문제