Permalink
Browse files

Ajax: trigger error callback on native abort

- IE9 does not have onabort. Use onreadystatechange instead.

Fixes gh-2079
Close gh-2684
  • Loading branch information...
timmywil committed Nov 2, 2015
1 parent 70605c8 commit 76e9a95dbeaf28fbc5a64571ebb5959f91a9c14a
Showing with 61 additions and 9 deletions.
  1. +41 −8 src/ajax/xhr.js
  2. +20 −1 test/unit/ajax.js
View
@@ -25,7 +25,7 @@ support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
support.ajax = xhrSupported = !!xhrSupported;
jQuery.ajaxTransport( function( options ) {
var callback;
var callback, errorCallback;
// Cross domain only allowed if supported through XMLHttpRequest
if ( support.cors || xhrSupported && !options.crossDomain ) {
@@ -72,17 +72,26 @@ jQuery.ajaxTransport( function( options ) {
callback = function( type ) {
return function() {
if ( callback ) {
callback = xhr.onload = xhr.onerror = null;
callback = errorCallback = xhr.onload =
xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
if ( type === "abort" ) {
xhr.abort();
} else if ( type === "error" ) {
complete(
// File: protocol always yields status 0; see #8605, #14207
xhr.status,
xhr.statusText
);
// Support: IE9
// On a manual native abort, IE9 throws
// errors on any property access that is not readyState
if ( typeof xhr.status !== "number" ) {
complete( 0, "error" );
} else {
complete(
// File: protocol always yields status 0; see #8605, #14207
xhr.status,
xhr.statusText
);
}
} else {
complete(
xhrSuccessStatus[ xhr.status ] || xhr.status,
@@ -103,7 +112,31 @@ jQuery.ajaxTransport( function( options ) {
// Listen to events
xhr.onload = callback();
xhr.onerror = callback( "error" );
errorCallback = xhr.onerror = callback( "error" );
// Support: IE9
// Use onreadystatechange to replace onabort
// to handle uncaught aborts
if ( xhr.onabort !== undefined ) {
xhr.onabort = errorCallback;
} else {
xhr.onreadystatechange = function() {
// Check readyState before timeout as it changes
if ( xhr.readyState === 4 ) {
// Allow onerror to be called first,
// but that will not handle a native abort
// Also, save errorCallback to a variable
// as xhr.onerror cannot be accessed
window.setTimeout( function() {
if ( callback ) {
errorCallback();
}
} );
}
};
}
// Create the abort callback
callback = callback( "abort" );
View
@@ -38,7 +38,7 @@ QUnit.module( "ajax", {
);
ajaxTest( "jQuery.ajax() - success callbacks", 8, function( assert ) {
return {
return {
setup: addGlobalEvents( "ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess", assert ),
url: url( "data/name.html" ),
beforeSend: function() {
@@ -437,6 +437,25 @@ QUnit.module( "ajax", {
};
} );
ajaxTest( "jQuery.ajax() - native abort", 2, function( assert ) {
return {
url: url( "data/name.php?wait=1" ),
xhr: function() {
var xhr = new window.XMLHttpRequest();
setTimeout( function() {
xhr.abort();
}, 100 );
return xhr;
},
error: function( xhr, msg ) {
assert.strictEqual( msg, "error", "Native abort triggers error callback" );
},
complete: function() {
assert.ok( true, "complete" );
}
};
} );
ajaxTest( "jQuery.ajax() - events with context", 12, function( assert ) {
var context = document.createElement( "div" );

0 comments on commit 76e9a95

Please sign in to comment.