2009-08-12 4 views
0

XMLHttpRequest, prevDataLength, nextreadPos 및 inProgress (잠금 용)에 대한 전역 변수를 사용하지 않고 JavaScript 처리에서 아직 처리되지 않은 XMLHttpRequest responseText의 일부만 onprogress/onreadystatechange 처리기에서만 처리합니까?전역 변수없이 XMLHttpRequest 응답의 처리되지 않은 부분을 처리하는 방법은 무엇입니까?

문제는 다음과 같습니다. 현재 AJAX (XMLHttprequest의 responseText의 현재 값)를 사용하여 얻은 데이터의 현재 수신 된 부분을 기반으로 웹 페이지를 업데이트하고 싶습니다. 서버가 데이터를 보내 자마자 바로 페이지를 업데이트하고 싶습니다 (소위 HTTP streaming pattern). 업데이트 할 때 아직 처리되지 않은 responseText 부분 만 처리하려고합니다.

추가적인 복잡성은 responseText가 응답의 미완성 조각을 포함 할 수 있다는 것입니다. 하나는 터미네이터를 사용하여 (내가하는 것처럼) 쉽게 처리 할 수 ​​있습니다. 그러면 완전한 응답을 쉽게 추출 할 수 있습니다.

현재 이전 호출이 작업 (새 데이터 처리)을 완료하지 않은 상태에서 처리기가 호출되는 문제를 방지하기 위해 전역 변수와 잠금을 사용합니다. 같은 내 코드 외모 (간체) 다음

function processData(unprocessed, nextReadPos) { 
    var lastLineEnd = unprocessed.lastIndexOf('\n'); 
    if (lastLineEnd !== -1) { 
     var lines = unprocessed.substring(0, lastLineEnd).split('\n'); 
     nextReadPos += lastLineEnd + 1 /* 1 == '\n'.length */; 

     processLines(lines); 
    } // end if 

    return nextReadPos; 
} 

function handleResponse() { 
    ... 
    // here xhr.readyState === 4 && xhr.status === 200 
    // in case we were called before finished processing 
    if (inProgress) { 
     return; 
    } else { 
     inProgress = true; 
    } 

    // extract new whole (complete) lines, and process them 
    while (prevDataLength !== xhr.responseText.length) { 
     if (xhr.readyState === 4 && 
      prevDataLength === xhr.responseText.length) { 
      break; 
     } 

     prevDataLength = xhr.responseText.length; 
     var unprocessed = xhr.responseText.substring(nextReadPos); 
     nextReadPos = processData(unprocessed, nextReadPos); 
    } // end while 
    ... 
    inProgress = false; 
} 
... 
xhr.onreadystatechange = handleResponse; 

나는 그것이 예를 들어, 같은 매개 변수로 XMLHttpRequest 객체를 전달하여 작업을 완료하지 않았을 때 내가 다시 입력 핸들러에 대해 보호 할 수 간단 핸들러가있는 경우 의 경우 1 "3 단계 - 간단한 예"모질라 개발자 센터에서 AJAX/Getting_Started 문서의 :

코드의 큰 조각에 사용 된 표기법

xhr.onreadystatechange = function() { handleResponse(xhr); }; //1 (simultaneous request) 

입니다

httpRequest.onreadystatechange = function() { alertContents(httpRequest); }; //1 (simultaneous request) 

그러나 예를하지 않는 다른 전역 변수와 관련하여 무엇을 할 지 말해주십시오 : prevDataLengthnextReadPos. 이들은 새로운 데이터가 있는지 결정하고 서버 응답으로부터 완전한 '문장'을 추출하는 데 사용됩니다.

글로벌 변수없이 어떻게 할 수 있습니까?

답변

1

임계 영역을 보호하기 위해 semaphor/뮤텍스로 사용

먼저 다른 답변, 전역 변수 inProgress이 없었다 때문에 나는 내 자신의 질문에 대답하고, 그리고 while (prevDataLength !== xhr.responseText.length) { ... } 루프는 전혀 필요하지 않습니다 . William's answerAre mutexes needed in JavaScript?에 StackOverflow의 질문에 따르면

:

자바 스크립트가 사용자에게 노출 스레딩이없는 의미 재진입 언어로 정의되고, 구현 스레드가있을 수 있습니다. setTimeout()과 같은 함수와 비동기 콜백은 스크립트 엔진이 실행되기 전에 대기해야합니다.

DOM 이벤트 모델 재진입은 다음과 같습니다

이것은 "Document Object Model (DOM) Level 3 Events W3C Specification"의 설명, 장, 절 1.2 "이벤트 파견 및 DOM 이벤트 흐름", 마지막 단락 1. "문서 객체 모델 이벤트"에 동의합니다. 이벤트 리스너는 추가 이벤트가 전달되도록하는 액션을 수행 할 수 있습니다.이러한 이벤트는 동기 방식으로 처리되며, 이벤트 리스너가 트리거되도록하는 이벤트 전파는 새 이벤트의 이벤트 디스패치가 완료된 후에 만 ​​재개됩니다.

즉, 이벤트에서 발생하는 모든 작업이 완료되어야 다음 이벤트가 처리됩니다. 둘째


, 전역 변수 prevDataLengthnextReadPos은 (아마도한다) XMLHttpRequest 객체에 추가 추가 속성으로 추가 할 수 있습니다. 더글러스 크록 포드에 의해 Private Members in JavaScript 다소 설명하고, comp.lang.javascript 자주 묻는 질문 노트 :: 자바 스크립트 클로저에서 Example 3: Encapsulating Related Functionality에로

대체 솔루션은 개인/정적 변수를 가지고 클로저를 사용하는 것입니다.

관련 문제