2016-06-13 2 views
0

완료하는 데 2 ​​일에서 3 일 정도 걸릴 수있는 이전 절차가 있습니다. 다음 구현에서는 재귀 적 측면으로 인해 StackOverFlow 예외가 발생할 수 있습니다. JavaScript가 실제로이 코드를 실행하기 위해 거대한 스택을 구축합니까? 그렇다면 더 나은 구현은 무엇입니까? 나는 약 1 천만 번이 서비스를 부를지도 모른다. $.ajax가 비동기자바 스크립트에서 재귀 호출 웹 서비스가 발생합니다. StackOverflow가 발생합니다.

function mainFunc() { 
     var url = getMyUrl(); 
     $.ajax({ 
      url: url, 
      type: "POST", 
      contentType: "application/json;charset=utf-8", 
      dataType: "json", 
      success: function (remaining) { 
       if(remaining > 0) { 
        mainFunc(); 
       } 
       else { 
        alert('done'); 
       } 
      }, 
      error: function (x, e) { 
       alert('error!'); 
      } 
     }); 
    } 

답변

1

우선, 이것은 확실히 브라우저에서 수행해야하는 것과 같지 않지만 대신 서버 측을 처리합니다.

즉, 재귀가 비동기식으로 발생하므로 스택 오버플로가 발생하지 않습니다.
정확한 코드 (구체적으로 어떤 값이 클로저에 정확히 포함되는지)에 따라 메모리 쌓기가 시작될 수 있습니다. mainFunc을 호출 할 때마다 성공과 오류 기능이 다시 생성되므로 메모리를 추가로 사용할 수도 있습니다.

이 함수의 메모리 할당 문제는 mainFunc 외부의 함수를 선언하고 mainFunc 함수 내부에서 참조를 전달하면 쉽게 해결할 수 있습니다.

이렇게해도 메모리 예외가 발생하는 것을 완전히 방지 할 수 있습니다. 이것은 실제로 실제 코드와 각 반복에서 유지하는 참조에 따라 다릅니다.

코드가이 긴 프로세스 동안 리소스에 걸려 있는지 확인하려면 코드를 읽고 "유출"코드가 어디에 있는지 알아 내거나 메모리 프로파일 링 옵션으로 다이빙하십시오 :

https://developer.chrome.com/devtools/docs/javascript-memory-profiling

예 밖으로 고려하는 폐쇄 :

function mainFuncSuccess(remaining) { 
    if(remaining > 0) { 
     mainFunc(); 
    } 
    else { 
     alert('done'); 
    } 
} 


function mainFuncError() { 
    alert('error!'); 
} 

function mainFunc() { 
     var url = getMyUrl(); 
     $.ajax({ 
      url: url, 
      type: "POST", 
      contentType: "application/json;charset=utf-8", 
      dataType: "json", 
      success: mainFuncSuccess, 
      error: mainFuncError 
     }); 
    } 
+0

이와 같은 기능을 외부에서 선언합니까? 'success : callSuccess (remaining);''callSuccess'가'mainFunc()'를 호출하는 곳? – yazanpro

+1

@yazanpro 아니요, 예제에 대한 업데이트 된 답변을 참조하십시오 –

+0

'mainFuncSuccess'에 매개 변수로'remaining'을 넣을 수 있는지 알고 있습니까? 'remaining'은 이제 정의되지 않았습니다. – yazanpro

1

때문에, 원격 서버가 응답 할 때까지 이후 success 함수를 호출 할 것이다. 즉, 반복이 끝날 때마다 JS 엔진은 응답을 얻을 때까지 본질적으로 '잠자기'한 다음 success 기능으로 다시 시작합니다. 따라서 이것은 기술적으로 재귀의 예가 아닙니다. 스택은 얼마나 많은 반복이 있더라도 (스택에 기여하는 다른 요소는 없다고 가정 할 때) 상당히 작아야합니다.

1

아니, 당신은 나중에 사용할 필요 mainFunc의 내부에 아무것도 저장하지 않는 때문이다. 함수의 범위에 저장되어야하는 객체가 없습니다.

크롬에서는 window.performance.memory로 메모리를 확인할 수 있습니다.

+0

스택 오버 플로우 (try'(function foo() {foo();})()))를 얻으려면 함수 외부에 아무것도 저장할 필요가 없습니다. –

+0

단순화 된 예입니다. 실제로 코드가 어떻게 보이는지 정확히 의존 할 것입니다. –

관련 문제