aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimmy Willison <timmywillisn@gmail.com>2015-11-02 12:00:28 -0500
committerTimmy Willison <timmywillisn@gmail.com>2015-11-03 12:34:04 -0500
commit76e9a95dbeaf28fbc5a64571ebb5959f91a9c14a (patch)
treeda3d2a0b211ca3c30677a3116bc7dcad896cc2d9
parent70605c8e5655da996ebd395e3c43423daaa08d9c (diff)
downloadjquery-76e9a95dbeaf28fbc5a64571ebb5959f91a9c14a.tar.gz
jquery-76e9a95dbeaf28fbc5a64571ebb5959f91a9c14a.zip
Ajax: trigger error callback on native abort
- IE9 does not have onabort. Use onreadystatechange instead. Fixes gh-2079 Close gh-2684
-rw-r--r--src/ajax/xhr.js49
-rw-r--r--test/unit/ajax.js21
2 files changed, 61 insertions, 9 deletions
diff --git a/src/ajax/xhr.js b/src/ajax/xhr.js
index 7ac141e64..fd4a733e5 100644
--- a/src/ajax/xhr.js
+++ b/src/ajax/xhr.js
@@ -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" );
diff --git a/test/unit/ajax.js b/test/unit/ajax.js
index 7710f9e35..4f0530656 100644
--- a/test/unit/ajax.js
+++ b/test/unit/ajax.js
@@ -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" );