Can I use jQuery prefilters to detect onreadystatechange events where readyState==3?
I'm trying to implement the XHR streaming Comet technique in jQuery, but am having some trouble detecting the onreadystatechange
event. I'm using Firefox 4.0.1.
I'm using prefilters (available since jQuery 1.5) to modify the native XHR object, specifically to add an event handler to the onreadystatechange
event. I've got a crude implementation of that at http://jsfiddle.net/Rdx6f/. That code appends to the document the XHR object's readyState
and responseText
attributes when the onreadystatechange
event is fired. Oddly, h开发者_如何转开发owever, it only seems to detect the onreadystatechange
event when readyState
is 1.
In other words, jQuery seems to be detecting the onreadystatechange
event when the XMLHttpRequest object is in state "opened" (readyState 1), but not when the XHR object is in state "headers received" (readyState 2), "loading" (readyState 3), nor "done" (readyState 4).
Oddly, if I alert()
in the event handler, then I do see the onreadystatechange
handling when readyState is 1, 2, 3 and 4. See http://jsfiddle.net/Rdx6f/1/. Same code as http://jsfiddle.net/Rdx6f/, just alert()
ing instead of appending to the document.
I can also detect onreadystatechange
events when readyState
is 1, 2, 3 or 4 in native JavaScript -- see http://jsfiddle.net/d7vaH/. (That code is taken almost verbatim from Dylan Schiemann's implementation of XHR streaming on page 115 of the book "Even Faster Websites".)
Am I simply doing something wrong here, like using jQuery's Ajax prefilters wrong or making a JavaScript mistake? Is this perhaps a bug in jQuery?
FYI: I looked into this quite deeply and it turns out that jQuery (since 1.5) uses the onreadystatechange event internally. The consequence of this is that jQuery will always write it's internal function to the onreadystatechange event, overwriting whatever you set it to. This happens whenever the AJAX call is actually sent, which means the function you wrote for onreadystatechange will work until that time (which means it will work until readyState = 1, but not longer).
This is the proposed workaround at the moment: http://jsfiddle.net/tBTW2/
At the moment, I cannot see a different (better) workaround without either not using jQuery (or going back to 1.4.4 or lower version, where it works perfectly) or editing the jQuery code (because as it is right now they will always overwrite whatever you try to hook in).
However, in upcoming versions (most likely in 1.8), the jQuery team are planning on implementing support for triggering events depending on the different readyStates. They will use Deferreds in some way.
This is the ticket that keeps this upcoming change:
http://bugs.jquery.com/ticket/9883
Here is the prefiltering done correctly linked from the jQuery bugzilla bug #8327,
http://jsfiddle.net/d8ckU/1/
精彩评论