Reworked script and xhr abort logic to take advantage of the fact jXHR.abort will complete the request itself if not done already.

This commit is contained in:
jaubourg 2011-01-13 02:05:39 +01:00
parent b07d43c649
commit 667a3b31e6
2 changed files with 36 additions and 42 deletions

View file

@ -47,7 +47,7 @@ jQuery.ajax.transport("script", function(s) {
script.src = s.url; script.src = s.url;
// Attach handlers for all browsers // Attach handlers for all browsers
script.onload = script.onreadystatechange = function( _ , statusText) { script.onload = script.onreadystatechange = function( _ , isAbort ) {
if ( ! script.readyState || /loaded|complete/.test( script.readyState ) ) { if ( ! script.readyState || /loaded|complete/.test( script.readyState ) ) {
@ -59,10 +59,13 @@ jQuery.ajax.transport("script", function(s) {
head.removeChild( script ); head.removeChild( script );
} }
// Dereference the script
script = 0; script = 0;
// Callback // Callback if not abort
callback( statusText ? 0 : 200, statusText || "success" ); if ( ! isAbort ) {
callback( 200, "success" );
}
} }
}; };
// Use insertBefore instead of appendChild to circumvent an IE6 bug. // Use insertBefore instead of appendChild to circumvent an IE6 bug.
@ -70,9 +73,9 @@ jQuery.ajax.transport("script", function(s) {
head.insertBefore( script, head.firstChild ); head.insertBefore( script, head.firstChild );
}, },
abort: function(statusText) { abort: function() {
if ( script ) { if ( script ) {
script.onload( 0 , statusText ); script.onload(0,1);
} }
} }
}; };

View file

@ -9,8 +9,8 @@ var // Next fake timer id
// XHR pool // XHR pool
xhrPool = [], xhrPool = [],
// #5280: see end of file // #5280: see below
xhrUnloadAbortMarker; xhrUnloadAbortInstalled;
jQuery.ajax.transport( function( s , determineDataType ) { jQuery.ajax.transport( function( s , determineDataType ) {
@ -25,25 +25,23 @@ jQuery.ajax.transport( function( s , determineDataType ) {
send: function(headers, complete) { send: function(headers, complete) {
// #5280: we need to abort on unload or IE will keep connections alive // #5280: we need to abort on unload or IE will keep connections alive
if ( ! xhrUnloadAbortMarker ) { if ( ! xhrUnloadAbortInstalled ) {
xhrUnloadAbortMarker = []; xhrUnloadAbortInstalled = 1;
jQuery(window).bind( "unload" , function() { jQuery(window).bind( "unload" , function() {
// Abort all pending requests // Abort all pending requests
jQuery.each(xhrs, function(_, xhr) { jQuery.each(xhrs, function(_, xhr) {
if ( xhr.onreadystatechange ) { if ( xhr.onreadystatechange ) {
xhr.onreadystatechange( xhrUnloadAbortMarker ); xhr.onreadystatechange( 1 );
} }
}); });
// Reset polling structure to be safe
xhrs = {};
}); });
} }
// Get a new xhr
var xhr = xhrPool.pop() || s.xhr(), var xhr = xhrPool.pop() || s.xhr(),
handle; handle;
@ -58,7 +56,7 @@ jQuery.ajax.transport( function( s , determineDataType ) {
// Requested-With header // Requested-With header
// Not set for crossDomain requests with no content // Not set for crossDomain requests with no content
// (see why at http://trac.dojotoolkit.org/ticket/9486) // (see why at http://trac.dojotoolkit.org/ticket/9486)
// Won't change header if already provided in beforeSend // Won't change header if already provided
if ( ! ( s.crossDomain && ! s.hasContent ) && ! headers["x-requested-with"] ) { if ( ! ( s.crossDomain && ! s.hasContent ) && ! headers["x-requested-with"] ) {
headers["x-requested-with"] = "XMLHttpRequest"; headers["x-requested-with"] = "XMLHttpRequest";
} }
@ -76,20 +74,23 @@ jQuery.ajax.transport( function( s , determineDataType ) {
try { try {
xhr.send( ( s.hasContent && s.data ) || null ); xhr.send( ( s.hasContent && s.data ) || null );
} catch(e) { } catch(e) {
// Store back in pool // Store back into pool
xhrPool.push( xhr ); xhrPool.push( xhr );
complete(0, "error", "" + e); complete(0, "error", "" + e);
return; return;
} }
// Listener // Listener
callback = function ( abortStatusText ) { callback = function( isAbort ) {
// Was never called and is aborted or complete // Was never called and is aborted or complete
if ( callback && ( abortStatusText || xhr.readyState === 4 ) ) { if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
// Do not listen anymore // Only called once
// and Store back in pool callback = 0;
// Do not keep as active anymore
// and store back into pool
if (handle) { if (handle) {
xhr.onreadystatechange = jQuery.noop; xhr.onreadystatechange = jQuery.noop;
delete xhrs[ handle ]; delete xhrs[ handle ];
@ -97,28 +98,20 @@ jQuery.ajax.transport( function( s , determineDataType ) {
xhrPool.push( xhr ); xhrPool.push( xhr );
} }
callback = 0; // If it's an abort
if ( isAbort ) {
// Get info
var status, statusText, response, responseHeaders;
if ( abortStatusText ) {
// Abort it manually if needed
if ( xhr.readyState !== 4 ) { if ( xhr.readyState !== 4 ) {
xhr.abort(); xhr.abort();
} }
// Stop here if unloadAbort
if ( abortStatusText === xhrUnloadAbortMarker ) {
return;
}
status = 0;
statusText = abortStatusText;
} else { } else {
status = xhr.status; // Get info
var status = xhr.status,
statusText,
response,
responseHeaders = xhr.getAllResponseHeaders();
try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests
@ -130,8 +123,6 @@ jQuery.ajax.transport( function( s , determineDataType ) {
} }
responseHeaders = xhr.getAllResponseHeaders();
// Filter status for non standard behaviours // Filter status for non standard behaviours
// (so many they seem to be the actual "standard") // (so many they seem to be the actual "standard")
status = status =
@ -164,10 +155,10 @@ jQuery.ajax.transport( function( s , determineDataType ) {
xhr.getResponseHeader("content-type"), xhr.getResponseHeader("content-type"),
xhr.responseText, xhr.responseText,
xhr.responseXML ); xhr.responseXML );
}
// Call complete // Call complete
complete(status,statusText,response,responseHeaders); complete(status,statusText,response,responseHeaders);
}
} }
}; };
@ -189,9 +180,9 @@ jQuery.ajax.transport( function( s , determineDataType ) {
} }
}, },
abort: function(statusText) { abort: function() {
if ( callback ) { if ( callback ) {
callback(statusText); callback(1);
} }
} }
}; };