Managing Multiple Async with when()
In this page:
$.when(promise1, promise2).done(function (result1, result2) {
// all resolved
});
What is when()?
$.when() takes one or more Deferred objects or promises and returns a single combined promise that only settles once every one of them has settled. It's the tool for waiting on several independent asynchronous operations before continuing, instead of nesting their callbacks inside each other.
Example: What is when()?
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<div id="output"></div>
<script>
$("#runBtn").click(function() {
const a = $.Deferred();
const b = $.Deferred();
$.when(a, b).done(function() { $("#output").text("Both settled"); });
a.resolve();
b.resolve();
});
$("#resetBtn").click(function() {
$("#output").empty();
});
</script>
</body>
</html>
when with AJAX
when() is especially useful for combining multiple asynchronous requests — say, three separate AJAX calls needed to build one page — so the final callback only runs after every request has come back successfully.
Example: when with AJAX
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<div id="output"></div>
<script>
$(document).ajaxError(function(event, xhr, settings) {
$("#output").append($("<div>").text("Request failed: " + settings.url));
});
$("#runBtn").click(function() {
$("#output").empty();
$("#output").append($("<div>").text("Sending request..."));
$.when($.get("data.php"), $.get("data.php")).done(function(r1, r2) {
$("#output").text("Both requests finished");
});
});
$("#resetBtn").click(function() {
jQuery(document).off();
$("#output").empty();
});
</script>
</body>
</html>
Handle Failure
If any one of the combined operations fails, the fail() callback on the combined promise runs instead of done(), which is useful when the overall task genuinely requires every one of the individual pieces to succeed. A single failure is enough to mark the whole combined operation as failed.
Example: Handle Failure
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<div id="output"></div>
<script>
$("#runBtn").click(function() {
const a = $.Deferred();
const b = $.Deferred();
$.when(a, b).fail(function() { $("#output").text("At least one failed"); });
a.resolve();
b.reject();
});
$("#resetBtn").click(function() {
$("#output").empty();
});
</script>
</body>
</html>
Use Different Delays
The individual operations passed to when() can take different amounts of time to complete, and when() will wait for the slowest one before resolving — it settles only once every operation it's tracking has finished. This makes it reliable even when the underlying tasks vary widely in duration.
Example: Use Different Delays
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<div id="output"></div>
<script>
$("#runBtn").click(function() {
const fast = $.Deferred();
const slow = $.Deferred();
setTimeout(function() { fast.resolve(); }, 50);
setTimeout(function() { slow.resolve(); }, 300);
$.when(fast, slow).done(function() { $("#output").text("Both finished, waited for slowest"); });
});
$("#resetBtn").click(function() {
$("#output").empty();
});
</script>
</body>
</html>
Small when() Project
when() is especially valuable on pages that need several independent pieces of data — like a user profile, their recent orders, and site settings — before they can render, letting you wait for all three at once instead of chaining them unnecessarily.
Example: Small when() Project
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<div id="output"></div>
<script>
$(document).ajaxError(function(event, xhr, settings) {
$("#output").append($("<div>").text("Request failed: " + settings.url));
});
$("#runBtn").click(function() {
$("#output").empty();
$("#output").append($("<div>").text("Sending request..."));
$.when($.get("data.php"), $.get("data.php"), $.get("data.php")).done(function() {
$("#output").text("Profile, orders, and settings all loaded");
});
});
$("#resetBtn").click(function() {
jQuery(document).off();
$("#output").empty();
});
</script>
</body>
</html>
- Passing the results of calling functions instead of the promises, or a value with no promise, when
$.when()needs Deferred objects such as$.when($.get(...), $.get(...)). - Expecting
done()to receive plain values for AJAX calls, when each argument is an array like[data, status, jqXHR]. - Assuming
fail()waits for all the tasks, when it fires as soon as one fails and does not wait for the others.
- Deferred objects represent work that finishes later, with states such as pending, resolved, and rejected.
- You create and resolve deferreds and chain steps with promise pipeline methods.
when()manages multiple asynchronous tasks together.
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: