Deferred States
In this page:
var dfd = $.Deferred(); // state: "pending"
dfd.resolve(value); // state: "resolved" -> done() runs
dfd.reject(reason); // state: "rejected" -> fail() runs
dfd.state(); // read the current state
Pending State
Every new Deferred starts out in the pending state, meaning its underlying task hasn't finished in either direction yet. Pending is always the starting point — a Deferred can only move forward from here to one of two possible outcomes.
Example: Pending State
<!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 dfd = $.Deferred();
$("#output").text(String(dfd.state()));
});
$("#resetBtn").click(function() {
$("#output").empty();
});
</script>
</body>
</html>
Resolved State
When resolve() is called on a Deferred, it moves to the resolved state, and any done() callbacks attached to it are called immediately with the values passed to resolve(). This is how a Deferred announces that its task completed successfully.
Example: Resolved State
<!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 dfd = $.Deferred();
dfd.done(function(value) { $("#output").text(String(value)); });
dfd.resolve("done!");
});
$("#resetBtn").click(function() {
$("#output").empty();
});
</script>
</body>
</html>
Rejected State
When reject() is called on a Deferred, it moves to the rejected state, and any fail() callbacks attached to it are called with the values passed to reject(). This is the Deferred's way of announcing that the underlying task failed.
Example: Rejected State
<!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 dfd = $.Deferred();
dfd.fail(function(reason) { $("#output").text(String(reason)); });
dfd.reject("something failed");
});
$("#resetBtn").click(function() {
$("#output").empty();
});
</script>
</body>
</html>
State Cannot Go Back
Once a Deferred is resolved or rejected, its state cannot go back to pending or switch to the other outcome — the final state is permanent. This one-way transition is what makes a Deferred reliable to depend on: once you know it settled, you know that outcome won't change.
Example: State Cannot Go Back
<!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 dfd = $.Deferred();
dfd.resolve();
$("#output").text(String(dfd.state()));
dfd.reject();
// has no effect, already resolved
});
$("#resetBtn").click(function() {
$("#output").empty();
});
</script>
</body>
</html>
Check State in a Task
The state() method returns the current state as a string (pending, resolved, or rejected), which is useful when you need to check where an asynchronous task currently stands without attaching a new callback to find out.
Example: Check State in a Task
<!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 dfd = $.Deferred();
if (dfd.state() === "pending") {
$("#output").text("Still working");
}
});
$("#resetBtn").click(function() {
$("#output").empty();
});
</script>
</body>
</html>
- Trying to change a Deferred's state after it has settled, such as calling
reject()afterresolve(), when the state is final and the second call is ignored. - Checking
dfd.state()right after starting async work and expecting"resolved", when it is still"pending". - Confusing
"rejected"with an error thrown in code, when it only meansreject()was called.
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: