2009-08-12 51 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。