XMLHttpRequest abort() behavior and event triggering in IE10
0 reputation · 26 Feb 2024, 20:39 UTC
0 reputation · 26 Feb 2024, 20:39 UTC
In Internet Explorer 10, managing the lifecycle of asynchronous HTTP requests requires manual handling of the XMLHttpRequest object, as the modern AbortController API is unavailable. While the .abort() method is the documented way to terminate a pending request, there is uncertainty regarding the resulting event sequence.
The goal is to implement a consistent cancellation pattern that distinguishes between a user-initiated abort and a network-level failure. Depending on the current readyState of the request, calling .abort() may trigger different callbacks, potentially leading to redundant error handling logic.
.abort() consistently trigger the onerror event in IE10 across all request states?readyState value is assigned to the request immediately following an abort operation?32775 reputation · 27 Feb 2024, 02:35 UTC
No — abort() does not trigger onerror in IE10. Abort and error are separate termination paths, so error-handling logic that lives only in onerror will never run for a user-initiated cancel. Instead, abort() fires the onabort handler, and you may also observe a readystatechange transition to readyState 4 (DONE) as part of the teardown. Immediately after abort() returns, the request's readyState is reset to 0 (UNSENT), and status/statusText are cleared.
Because an aborted request can pass through readyState 4, code like this misclassifies cancels as completions:
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
// WRONG: also runs after abort()
handleSuccess(xhr.responseText);
}
};Additionally, reading xhr.status or xhr.responseText after an abort is unreliable — the values are cleared, and in some IE states access can throw. Keep property reads out of the abort path.
Since IE10 has no AbortController, use an application-level flag set before calling abort(), and route all terminal logic through one dispatcher:
function makeRequest(url, onSuccess, onFailure) {
var xhr = new XMLHttpRequest();
var state = { aborted: false };
xhr.open('GET', url, true);
// Attach ALL handlers before send()
xhr.onabort = function () { finish('abort'); };
xhr.onerror = function () { finish('error'); };
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && !state.aborted) {
finish(xhr.status >= 200 && xhr.status < 300 ? 'success' : 'error');
}
};
function finish(outcome) {
if (state.aborted) return; // user cancel: stay silent
if (outcome === 'success') onSuccess(xhr.responseText);
else if (outcome === 'error') onFailure();
}
xhr.send();
return {
cancel: function () {
state.aborted = true; // flag FIRST
xhr.abort();
}
};
}Key points:
abort() — events may fire synchronously during the call.onabort, onerror, and onreadystatechange before send(); handlers assigned later miss the events.readyState 0 (never sent) or already completed — abort() is then a no-op that fires no events, which can corrupt your state tracking if unguarded.The exact event ordering (whether readystatechange-to-4 precedes or follows onabort) can vary depending on the readyState at the moment you call abort(). Do not depend on a fixed sequence — depend on the flag. Also, do not confuse IE10's standard XMLHttpRequest with the legacy XDomainRequest used for cross-origin calls in IE8/9, which has different semantics.
To verify in IE10 (or IE11's IE10 document mode):
onerror, onabort, and onreadystatechange; call abort() mid-flight. Confirm onerror never fires and onabort does.xhr.readyState immediately after abort() returns; confirm it is 0.send(), after send() before headers, during download) and record which events fire per state.onerror.One diagnostic detail that would change this advice: if you are seeing onerror fire on abort, check whether a wrapper library (jQuery, etc.) is synthesizing the error callback — native IE10 XHR does not.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.