2012-03-28 2 views
1

"이상한"방식으로 일을하는 경우 사과로 시작하고 싶습니다. 주로 C 개발자이고이 AJAX 문제를 내가하는 방식으로 해결하고 있습니다. C.JavaScript 동기식 Ajax 요청 Idiosyncrasies

메시지를 사용할 수있을 때까지 기다린 후 해당 메시지 하나만 보내고 연결을 끊는 "푸시 서버"에 연결할 스크립트가 있습니다. 클라이언트는 이후의 메시지를 청취하기 위해 연결을 다시 설정해야합니다.

가 나는 비동기 콜백 내에서 동기 AJAX 호출을 구현하여이 작업을 수행하기 위해 노력하고, 모든 때까지 차단합니다 (아마도? 내가 여기 JS의 나의 무지를 보여주는거야) DOM을 표시를 제외하고 그것을 작동 통화가 완료되었습니다.

매번 콜백을 호출하는 콜백을 사용하여 스택을 고갈시키고 싶지 않기 때문에 순전히 비동기식 호출로 수행하는 방법을 모르겠습니다.

 $.ajax({ 
      url: './recoverDevice', 
      data: JSON.stringify(requestData), 
      dataType: 'json', 
      type: 'POST', 
      success: function(j) 
      { 
       console.log(j); 
       if (j.success) 
       { 
        //Indefinitely listen for push messages from the server 

        var loopMore = true; 
        while(loopMore) 
        { 
         $.ajax({ 
          async: false, 
          url: './getPendingMessage', 
          dataType: 'json', 
          type: 'POST', 
          success: function(j) 
          { 
           //alert(j.message); 
           $("#progressBox").append("<li>" + j.message + "</li>"); 
           loopMore = !j.complete; 
          } 
         }); 
        } 

       } 
       else 
       { 
        $("#errorBox").show(); 
        $("#errorBox").text(j.errorMessage); 
       } 
      } 
     }); 

자, 논리적으로,이 코드 해야 일 :

는 코드입니다. 비동기 함수 내에서 동기 JS 호출을 통해 루프를 종료 할 때마다 메시지를받을 때마다 DOM에 추가 할 것이며 서버가 더 이상 메시지가 없으면 루프를 종료해야한다고 알립니다. 비동기 스레드를 종료하고 태스크를 완료하십시오.

문제는 DOM 액세스가 모두 개의 메시지를 수신하면 모두 병합 된 것처럼 보입니다. 즉 모든 메시지가 수신되고 비동기 스레드가 종료 된 후에 만 ​​추가가 발생합니다.

주석 처리 된 alert은 테스트되었습니다. 완벽하게이 작동합니다. 각 알림 다음에 메시지 상자가 생기고 다음 메시지 (나머지 코드는 그대로)까지 올바르게 일시 중지됩니다.

비동기 스레드가 종료 될 때까지 DOM 조작을 허용하지 않아 경쟁 조건으로부터 보호하기 위해 내 브라우저 (Chrome)가 일부 마법을 사용하고 있다고 생각하십니까? 또는 나는 표에서 벗어나서 틀린 나무를 여기에서 위로 짖고 있냐?

루프를 제거하고 async을 true로 설정하면 첫 번째 메시지가 올바르게 수신되지만 아무런 문제가 발생하지 않습니다.

function GetMessage() 
{ 
    $.ajax({ 
     async: true, 
     url: './getPendingMessage', 
     dataType: 'json', 
     type: 'POST', 
     success: function(j) 
     { 
      $("#progressBox").append("<li>" + j.message + "</li>"); 
      if (!j.complete) 
      { 
       GetMessage(); 
      } 
     } 
    }); 
} 

을하지만 시간이 지남에 (어떤?) 스택 오버 플로우가 발생할 것이다 :

물론 나는 이런 식으로 뭔가를 할 수 있습니다.

분명한 해결책은 비동기 호출을 사용하는 것입니다.하지만 잠시 멈추고 일종의 동기화 프리미티브를 통해 새 호출을 계속할 것을 신호로 보내지 만 JS에는 신호 프리미티브가 없습니다.

답변

0

이 하나를 알아 냈습니다. 왜 내가 전에 이것을 보지 못했지만, 후자의 코드 조각은 완벽하게 작동합니다. 나는 게시 할 때 그것을 깨닫지 못했지만 스택을 오버플로 할 수 없기 때문에 비동기 호출을 실행하고 종료 할 때마다 스택의 프레임을 넘을 수는 없습니다. 따라서 스택 프레임은 결코 2 ~ 3 개가 넘지 않습니다.비동기 호출은 외부에서 관리되며 스택에 없으므로 시작할 때마다 호출됩니다.

첫 번째 방법 (비동기 호출의 동기식 코드)이 작동하지 않는 이유에 대한 의견을 보내 주시면 감사하겠습니다.

+0

첫 번째 방법이 "작동하지 않음"한 이유는 단순히 브라우저 다시 그리기 알고리즘의 기능이었습니다. 단일 스레드 동기 js가 블로킹 중이므로 스레드가 브라우저를 처리하는 동안 다시 그리지 않습니다. 그러나 경고 상자가 나타나면 다시 그리지 않습니다 (코드는 여전히 동기적이고 의미 상 차단되지만 후드 알고리즘에서는 다시 그리기 알고리즘과 관련하여 대기/비 차단 상태가 있다고 가정합니다). 이는 이유입니다 아마도 경보로 괜찮아 보였을 것입니다. 그냥 구현 뉘앙스. – davin

+0

하지만 동기 js 코드가 이미 비동기 js 스레드에서 호출되고 있습니다 ..? –

+1

그건 중요하지 않습니다. 왜 그렇게 생각하는지 모르겠습니다. "비동기 스레드"는 실제로 많은 의미가 없습니다. 코드 조각이 이벤트 루프에 다시 들어가면 다른 코드와 구별 할 수 없으므로 실행이 동기식으로 시작되었는지 여부에 관계없이 현재 실행은 동기식입니다. 사람들이 걸어 다니고 다른 사람들이 차를 타고 (동기식 대 비동기식, 비유 할 수있는 최고의 비유는 아니지만) 파티에 도착하는 것과 같습니다. 일단 도착하면 보안별로 하나씩 점검됩니다. – davin