How in JavaScript process unhandled yet part of XMLHttpRequest responseText only in onprogress/onreadystatechange handler, without using global variables for XMLHttpRequest, prevDataLength, nextreadPos and inProgress (for locking)?
The problem is the following: I want to update web page based on currently received part of data obtained using AJAX (current value of responseText of XMLHttprequest). I want to update page as soon as server sends data (it is so called HTTP streaming pattern). When I do update, I want to process only yet unhandled part of responseText.
Additional complication is that responseText may contain unfinished fragment of response; one can easily deal with that (like I do) by using terminators; then you can easily extract complete responses.
Currently I use global variables and locking to avoid problem where handler is called while earlier call didn't finished working (processing new data). My code looks (simplified) like the following:
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;
If I have simpler handler I could protect against re-entering handler when it didn't finish work by passing XMLHttpRequest object as parameter, like e.g. case 1 in "Step 3 – A Simple Example" section of AJAX/Getting_Started article at Mozilla Developer Centre:
httpRequest.onreadystatechange = function() { alertContents(httpRequest); }; //1 (simultaneous request)
which in notation used in larger fragment of code is
xhr.onreadystatechange = function() { handleResponse(xhr); }; //1 (simultaneous request)
But that example doesn't tell me what to do with other global variables: prevDataLength
and nextReadPos
. They are used to decide if there is any new data, and to extract complete 'sentences' from server response, respectively.
How to do that without global variables?