Understanding JavaScript Asynchronous Execution and setTimeout Pitfalls Through a Real-World jQuery Ajax Timeout Case
The article explains JavaScript's single‑threaded, event‑loop based asynchronous model, demonstrates how setTimeout’s imprecise timing can cause unexpected behavior in a jQuery Ajax timeout scenario, and offers practical guidance to avoid relying on exact timer scheduling.
JavaScript runs in the browser on a single main thread, so built‑in functions like alert block subsequent code execution until the dialog is dismissed.
Because the language is single‑threaded, all JavaScript originates from three sources: BOM APIs, DOM APIs, and user‑written ECMAScript.
The setTimeout API schedules a callback after a specified delay, but it only guarantees that the callback will be placed on the task queue after the delay; actual execution depends on when the event loop can dispatch it to the idle main thread.
To illustrate the problem, the article presents a real case where a jQuery $.ajax() request sets an extremely short timeout (15 ms). The failure callback ( fail ) retries the request and shows an alert , which blocks the main thread.
Relevant code snippets:
setTimeout(delayCode, 3000)and the simplified request logic:
function asyncRequest() {
$.ajax({
url: 'https://api.example.rs',
timeout: 15
}).then(success, fail);
}
function success(data) {
// handle data
}
function fail(xhr, errtext, errthrown) {
asyncRequest(); // retry
alert('请求超时');
}
asyncRequest();jQuery’s internal timeout handling uses another setTimeout to call abort('timeout') after the configured period:
if (s.async && s.timeout > 0) {
timeoutTimer = window.setTimeout(function () {
jqXHR.abort('timeout');
}, s.timeout);
}When the first request times out, the abort timer is queued and, because the main thread is free, it runs promptly, cancelling the request and invoking fail . The second request, however, shows an alert before the timer fires, keeping the main thread busy. The abort timer remains in the task queue until the user dismisses the dialog, by which time the Ajax response has already arrived and the success callback has been queued.
Consequently, the abort timer executes after the request has succeeded, having no effect, and the fail callback never runs. This demonstrates how relying on setTimeout for precise timing is unsafe, especially when UI blocking operations like alert are involved.
The takeaway is to avoid depending on exact timer scheduling in JavaScript logic; instead, use more reliable mechanisms (e.g., proper timeout values, promises, or abort controllers) and avoid blocking the main thread with modal dialogs.
360 Tech Engineering
Official tech channel of 360, building the most professional technology aggregation platform for the brand.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.