2013-11-04 2 views
0

나는 C++ 배경에서 왔기 때문에 콜백 메커니즘에 대해서는 명확하지 않다. 자바 스크립트와 혼동하여 재귀를 달성하지 못했습니다. 누군가 제발 도와주세요.자바 스크립트에서 재귀를 실현

이것은 내가 달성하기를 원하는 것입니다.

Method 1(on success - call Method2); 
Method 2(on success - call Method3); 
Method 3(on success - call Method1) 

다음은 내 코드입니다.

function Method1(val1, val2, callback) { 
    console.log('Method1' + val1); 
    callback(val1, Method3); 
} 

function Method2(val1, fn) { 
    console.log('Method2 ' + val1); 
    val1++; 
    fn(val1); 
} 

function Method3(val){ 
    console.log('Method3 ' + val); 
    val++; 
    if(val > 1000) process.exit(0); 
    else { 
     Method1(val,2, Method2); 
    } 
} 

Method1(1,2,Method2); 

나는이 실행되면이 발생 오류 RangeError : 최대 호출 스택의 크기가 오류를 초과했습니다. 자바 스크립트에서 재귀를 달성하는 방법?

편집 : 나는 웹 크롤러를 쓰고 있습니다. 이것이 내가 원하는 것입니다.

1. Get the URL to be crawled. 
2. Store the content(webpage) in a file. 
3. Parse the content. Get all the links in the file. 
4. call step 2 for each link in the content. 

은 재귀에 달성 될 수있다. 나는 종점/종점이 있어야한다는 것을 이해했다. 일단 모든 웹 링크를 구문 분석하면 내 종료 지점이 될 수 있습니다. 종료해야합니다.

+0

재귀 흐름이 멈추지 않습니다. – kbec

+0

지금 추가했습니다. 백만 시간 이상 재귀를 수행해야합니다. – swastican

+0

자바 스크립트는 꼬리 호출 최적화를 지원하지 않습니다. 모든 것이 스택에 푸시되지만 끝까지 도달 할 때까지 팝업되지 않습니다. 종료 조건이 충족되기 전에 스택 크기를 최대화합니다. – thgaskell

답변

2

언제 중지해야하는지, 아니면 각 방법을 계속 호출하여 오류가 발생합니다.

+0

실제로 C++ 또는 다른 언어와 매우 비슷합니다. 감사합니다. @thgaskell. –

0
function Method1(<params>){ 
    // condition 
    if(<params>){ 
     Method2(<params>); 
    }else{ 
     return; 
    } 

} 

function Method2(<params>){ 
    // condition 
    if(<params>){ 
     Method3(<params>); 
    }else{ 
     return; 
    } 
} 

function Method3(<params>){ 
    // condition 
    if(<params>){ 
     Method1(<params>); 
    }else{ 
     return; 
    } 
} 

Method1(<params>); 

참고 : 재귀 루프를 끊을 조건이 필요합니다. 그렇지 않으면 루프가 종료되지 않습니다.

1

자바는 꼬리 전화 최적화를 지원하지 않습니다. 모든 것이 스택에 푸시되지만 끝까지 도달 할 때까지 팝업되지 않습니다.

최종 조건이 충족되기 전에 스택 크기를 최대화하고 있습니다.

is there any way to overcome that ?

다양한 방법이 있습니다,하지만 난 간단한 나중에 매개 변수로 함수를 호출하기 위해 사용 setTimeout을 설정 될 것입니다 생각합니다. 예를 들어


:

function count(n, end) { 
    console.log(n); 
    if (n < end) { 
     count(n+1, end); 
    } 
} 
count(0, 100000) // More than enough to exceed the stack limit 

이 0 ~ 100000 모든 숫자를 인쇄하려고하지만, 그것은 끝에 도달하기 전에이 최대 스택 크기를했다.


그래서 대신에 직접 전화, 당신은 기능을합니다 setTimeout 함수로 전달하여 실행 시간을 연기 할 수 있으며,이 매개 변수를 그리고 나중에 실행합니다. setTimeout을 사용하는 것의 또 다른 이점은 호출이 비동기적일 수 있다는 것입니다. 즉, 그 동안 다른 코드가 실행될 수 있습니다. 일정이 어떻게 작동하는지에

function count(n, end) { 
    console.log(from); 
    if (n < end) { 
     setTimeout(count, 0, n+1, end); 
    } 
} 
count(0, 100000) // More than enough to exceed the stack limit, but it will run! 

더 많은 : 그것은 setImmediate 또는에서는 setTimeout 또는 process.nextTick (nodejs) 기능에 의해 달성 될 수있다 http://ejohn.org/blog/how-javascript-timers-work/

+1

. setTimeout이 작동해야합니다. 하지만 나는 setImmediate를 사용했다. http://nodejs.org/api/timers.html#timers_setimmediate_callback_arg IE 10에서만 지원되며 프런트 엔드 용 다른 브라우저에서는 아직 지원되지 않습니다. – swastican

0

. 효율적인 방법은 setImmediate입니다. 아래 링크에 나와있는 이유.

Setimmdiate API (SO) nextTick 대 http://nodejs.org/api/timers.html#timers_setimmediate_callback_arg
SetImmediate : setImmediate vs. nextTick
설명 1 : http://www.nczonline.net/blog/2013/07/09/the-case-for-setimmediate/
설명 2 : http://howtonode.org/understanding-process-next-tick

SetImmediate 내 지식에 따라 일부 브라우저에서 지원되지 않습니다. IE10에서만 지원됩니다. 서버 측에서 nodejs는 이러한 api를 지원합니다.