2009-08-12 48 views
0

如何在JavaScript中處理未處理的XMLHttpRequest responseText的一部分,僅在onprogress/onreadystatechange處理程序中使用,而不使用XMLHttpRequest,prevDataLength,nextreadPos和inProgress(用於鎖定)的全局變量?如何處理沒有全局變量的未處理的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製品的Mozilla開發者中心部:

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

這在較大的代碼片段所用符號是

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

但是,例如不告訴我如何處理其他全局變量:prevDataLengthnextReadPos。它們被用來決定是否有新的數據,並分別從服務器響應中提取完整的「句子」。

如何做到沒有全局變量?

回答

1

我回答我的問題,因爲沒有其他的答案

首先,全局變量inProgress,作爲semaphor /互斥體,以保護重要的部分,並且不需要while (prevDataLength !== xhr.responseText.length) { ... }循環可言。

根據William's answerAre mutexes needed in JavaScript? StackOverflow的問題:

JavaScript是定義爲折返語言,這意味着沒有螺紋暴露給用戶,有可能是在執行線程。像setTimeout()和異步回調函數需要等待腳本引擎在能夠運行之前進入睡眠狀態。

這同在"Document Object Model (DOM) Level 3 Events W3C Specification"說明,第1章「文檔對象模型事件」,1.2節「事件調度和DOM事件流」,最後一段:

的DOM事件模型折返。事件監聽器可能會執行導致發送其他事件的操作。這些事件以同步方式處理,導致事件監聽器被觸發的事件傳播只有在新事件的事件分派完成後纔會恢復。

這意味着在處理下一個事件之前,事件中發生的所有事情都必須完成。


其次,全局變量prevDataLengthnextReadPos可以(並且可能應該)被作爲附加額外的屬性,以XmlHttpRequest對象

替代解決方案是使用閉包來獲得私有/靜態變量,如Douglas Crockford在Private Members in JavaScript中所述,在comp.lang.javascript中在Example 3: Encapsulating Related Functionality中有所描述常見問題解答:: Javascript Closures。