Javascript 如何在没有全局变量的情况下处理XMLHttpRequest响应的未处理部分?
如何在JavaScript进程中,仅在onprogress/onreadystatechange处理程序中未处理XMLHttpRequest响应文本的一部分,而不使用XMLHttpRequest、prevDataLength、nextreadPos和inProgress(用于锁定)的全局变量 问题如下:我想根据使用AJAX(XMLHttprequest的responseText的当前值)获得的当前接收到的部分数据更新网页。我想在服务器发送数据后立即更新页面(这就是所谓的页面)。当我进行更新时,我只想处理responseText中尚未处理的部分 另一个复杂因素是responseText可能包含未完成的响应片段;人们可以通过使用终结者很容易地解决这个问题(就像我一样);然后您可以轻松提取完整的响应 目前,我使用全局变量和锁定来避免在调用处理程序时出现问题,而之前的调用并没有完成(处理新数据)。我的代码看起来(简化)如下所示:Javascript 如何在没有全局变量的情况下处理XMLHttpRequest响应的未处理部分?,javascript,ajax,streaming,xmlhttprequest,Javascript,Ajax,Streaming,Xmlhttprequest,如何在JavaScript进程中,仅在onprogress/onreadystatechange处理程序中未处理XMLHttpRequest响应文本的一部分,而不使用XMLHttpRequest、prevDataLength、nextreadPos和inProgress(用于锁定)的全局变量 问题如下:我想根据使用AJAX(XMLHttprequest的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对象作为参数传递来防止在处理程序未完成工作时重新输入处理程序,例如Mozilla Developer Center文章“步骤3–简单示例”部分的案例1:
httpRequest.onreadystatechange = function() { alertContents(httpRequest); }; //1 (simultaneous request)
在较大代码段中使用的符号是
xhr.onreadystatechange = function() { handleResponse(xhr); }; //1 (simultaneous request)
但是这个例子没有告诉我如何处理其他全局变量:prevDataLength
和nextradepos
。它们分别用于确定是否有任何新数据,以及从服务器响应中提取完整的“句子”
在没有全局变量的情况下如何做到这一点?我回答我自己的问题,因为没有其他答案
首先,全局变量inProgress
,用作信号量/互斥来保护关键部分,而while(prevDataLength!==xhr.responseText.length){…}
循环根本不需要
根据问题:
Javascript被定义为可重入语言,这意味着没有线程暴露给用户,实现中可能有线程。类似于setTimeout()
和异步回调的函数需要等待脚本引擎睡眠后才能运行
这与第1章中的描述一致。“文档对象模型事件”,第1.2节“事件分派和DOM事件流”,最后一段:
DOM事件模型是可重入的。事件侦听器可以执行导致调度其他事件的操作。此类事件以同步方式处理,导致触发事件侦听器的事件传播将仅在新事件的事件分派完成后恢复
这意味着在处理下一个事件之前,必须完成事件中发生的所有事情
其次,全局变量
prevDataLength
和nextradepos
可以(也可能应该)作为附加属性添加到XmlHttpRequest对象中
另一种解决方案是使用闭包来拥有私有/静态变量,如Douglas Crockford和comp.lang.javascript常见问题解答注释::javascript闭包中所述