Async iterator disposal turns cleanup into a Promise protocol. The hook creates a Promise capability before reading return, adopts whatever the return method produces and fulfils with undefined only after successful cleanup. Lookup, call and adopted-result failures appear as rejections rather than ordinary synchronous returns.
This specialist guide belongs to the Websites root. It also connects to The Gold Standard of Education | Learning That Transfers into Life and the How X Works hub. The worked cases are original teaching examples; their numbers are stipulated so that the reasoning can be checked.
eduKateSG · Websites
Find your next learning step
Trace async iterator disposal Promise creation, return lookup, result adoption, fulfilment-value discard and rejection timing.
ROUTE 1 · CHAPTERS 1–3
Build the protocol model
Identify setup, source ownership and the first decisive event.
ROUTE 2 · CHAPTERS 4–6
Trace normal progress
Follow opening, pulls, yields, completion and returned values in order.
ROUTE 3 · CHAPTERS 7–9
Change one condition
Rebuild the trace when order, length, cleanup or timing changes.
ROUTE 4 · CHAPTERS 10–12
Handle errors and limits
Distinguish abrupt completion, cleanup evidence and bounded claims.
ROUTE 5 · CHAPTERS 13–15
Test and explain
Design decisive fixtures, review code and transfer the reasoning.
Chapter contents
Build the protocol model · Chapters 1–3
1. Locate the async iterator disposal hook
Trace normal progress · Chapters 4–6
4. Call return with no arguments and the receiver
Change one condition · Chapters 7–9
7. Use await using for scope cleanup
Handle errors and limits · Chapters 10–12
Test and explain · Chapters 13–15
13. Compare sync and async disposal results
CHAPTER 1 OF 15 · Build the protocol model
1. Locate the async iterator disposal hook
%AsyncIteratorPrototype%[Symbol.asyncDispose] requests cleanup through an async iterator return method and always returns a Promise. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. An async generator inherits the hook; calling it produces a Promise before cleanup settlement is observed. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Use an async iterator with no return method and the returned Promise fulfils with undefined. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. The async hook is not merely the synchronous hook wrapped by caller convention. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
CHAPTER 2 OF 15 · Build the protocol model
2. Create a new Promise capability immediately
The algorithm creates a %Promise% capability before it looks up return, so even lookup failures are represented as rejection. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. A throwing return getter makes Symbol.asyncDispose return a rejected Promise rather than throwing synchronously to the caller. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Use a safe getter and observe a pending or fulfilled Promise path. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. Code must inspect settlement; a try block without await may miss the failure. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
As with synchronous disposal, the return property is read when the hook runs, not captured when the async iterator was created. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. Replace return after one next; the later async disposal uses the new function. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Set return to undefined and the Promise resolves to undefined. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. The receiver may change between production and cleanup. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
CHAPTER 4 OF 15 · Trace normal progress
4. Call return with no arguments and the receiver
When callable, return is invoked with the async iterator as this and no argument list. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. A custom async return logs binding and returns a delayed Promise. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Detach the function and compare its receiver-dependent behaviour. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. No final value is forwarded through the disposal hook. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
CHAPTER 5 OF 15 · Trace normal progress
5. Adopt the return result with PromiseResolve
The result of return is passed through PromiseResolve(%Promise%, result), so plain values and thenables become an awaited settlement path. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. Return a thenable that fulfils after logging; disposal waits for that adoption. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Return plain 7 and the result wrapper fulfils promptly. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. The hook does not expose 7 as its final fulfilment value. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
CHAPTER 6 OF 15 · Trace normal progress
6. Fulfil with undefined after successful cleanup
An internal fulfilment handler discards the adopted result and resolves the disposal Promise with undefined. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. return resolves to {done:true,value:9}; awaiting async disposal produces undefined. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Make return reject and the disposal Promise rejects instead. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. Discarded fulfilment data and preserved failure are different rules. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
An await using declaration registers asynchronous disposal and waits for its Promise during scope exit. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. Consume one async value, leave the block and observe return start, delayed cleanup, then continuation after fulfilment. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Use using rather than await using only where the resource offers synchronous disposal. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. Leaving lexical scope can now include asynchronous work. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
CHAPTER 8 OF 15 · Change one condition
8. Separate async disposal from for-await-of closing
A for-await-of break performs async iterator closing under loop semantics, while await using invokes Symbol.asyncDispose at resource-scope exit. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. Two logging fixtures both reach return but through different initiating operations. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Combine registration with an early loop break and make return idempotent to handle multiple requests safely. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. Similar awaited cleanup does not erase the semantic distinction. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
If GetMethod(return) is abrupt, IfAbruptRejectPromise rejects the created capability and the method returns that Promise. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. A getter throws Error E; calling the hook returns normally with a Promise that rejects with E. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Move E into the return body and compare the later but still rejected path. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. Synchronous observation of the call is insufficient evidence of success. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
CHAPTER 10 OF 15 · Handle errors and limits
10. Represent call failure as rejection
If calling return throws before producing a result, the capability rejects with that exception. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. return logs then throws; awaiting disposal rejects and no PromiseResolve adoption follows. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Return Promise.reject(E) instead and rejection arrives through the adopted result. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. Both reject, but event order reveals different failure points. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
A returned thenable may call its reject continuation; PerformPromiseThen forwards that failure to the disposal capability. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. A thenable getter and then method log before rejection reaches await. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Return a fulfilled thenable to reach the undefined fulfilment handler. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. Thenable assimilation can add user-code effects during cleanup. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
CHAPTER 12 OF 15 · Handle errors and limits
12. Avoid assuming every async iterator inherits the hook
A plain object with next returning Promises may satisfy an async-iterator protocol in context without inheriting %AsyncIteratorPrototype%. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. Inspect a custom object and find Symbol.asyncDispose absent. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Use an async generator instance and observe inherited availability. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. Protocol shape does not guarantee the standard prototype chain. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
Sync disposal can throw directly and returns undefined; async disposal returns a Promise and turns lookup or call failures into rejections. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. Run paired custom iterators whose return methods both fail and compare call-site control flow. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Make both succeed and compare immediate undefined with awaited undefined. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. The shared word disposal does not imply identical error timing. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
A decisive fixture logs call return, thenable adoption, microtask-visible settlement and continuation after await. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. Use a controllable Promise from return and prove the scope does not continue until it settles. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Resolve versus reject the same Promise to isolate the final branch. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. A final value assertion alone cannot prove cleanup was awaited. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
A complete account states capability creation, return lookup and call, result adoption, fulfilment-value discard or rejection, and caller await. Start by naming the object that owns the protocol step, the operation that triggers it and the state visible before that step. This prevents a familiar output from hiding earlier validation, property access or iterator creation.
Worked case. Report that async disposal returned a Promise, adopted return cleanup, then fulfilled undefined before execution continued. Record a ledger with columns for call time, source opening, next, return, value, completion and caller observation. The ledger must show every event that the conclusion depends on, including work that happens before the first yielded value.
Reason from the ledger rather than from the final array or log line. Mark the first event that selects the branch, then follow which sources remain open, which values have already been consumed and what completion reaches the caller. Those intermediate facts explain the result.
Changed-context check. Changed report: the return getter threw, so the returned Promise rejected without a cleanup call. Rebuild the sequence from the changed premise. Do not edit only the output: compare setup effects, pull counts, closing calls, rejected promises or property order wherever the mechanism makes them observable.
Limit and misconception check. Do not say async disposal waits by blocking the thread; it coordinates through Promise settlement. State the narrow conclusion supported by the fixture. Ordinary finite generators cannot establish every behaviour of proxies, host resources, unbounded sources, re-entrant callbacks or custom methods with additional side effects.
For a practical evidence check, instrument the relevant getters, iterator-opening methods, next and return methods, plus promise settlement when the path is asynchronous. Assert the ordered event log alongside the returned values. Output-only assertions often pass while cleanup or timing is wrong.
A useful review separates source behaviour from coordination behaviour and caller behaviour. The source decides what next or return does; the built-in operation decides when to call it; the caller observes a value, done result, exception or promise. Mixing these layers creates false causal stories.
Transfer the chapter into a compact explanation: state the starting state, the decisive algorithm step, the observed result and one caveat. Then change one condition and predict the new first divergence. This turns a memorised example into a reusable protocol model.
Continue with connected lessons
Trace Array.fromAsync awaited pulls
Trace Array.fromAsync awaited pulls. Compare async source consumption with explicit async cleanup.
Compare synchronous iterator disposal and closing
Compare synchronous iterator disposal and closing. Keep loop closing and synchronous failure timing distinct.
Trace cleanup failures through Promise.finally
Trace cleanup failures through Promise.finally. Review how a cleanup failure can alter an asynchronous outcome.
Frequently asked questions
What does Symbol.asyncDispose return?
A Promise.
What if the iterator has no return method?
The Promise fulfils with undefined.
Is the return result exposed?
No. A successful adopted result is discarded and fulfilment becomes undefined.
What if the return getter throws?
The returned Promise rejects with that error.
What if return returns a thenable?
The method adopts its settlement through PromiseResolve.
How does this differ from synchronous disposal?
Synchronous disposal returns undefined directly and can throw directly; async disposal settles a Promise.
Authoritative sources and further reading
ECMAScript: %AsyncIteratorPrototype%[Symbol.asyncDispose]. Normative Promise capability, return call, adoption and settlement.
ECMAScript: PromiseResolve. Adoption of cleanup return values and thenables.
ECMAScript: AsyncDisposable interface. Meaning of asynchronous cleanup and completion through fulfilment.
Return to the Websites subject guide, The Gold Standard of Education, or the How X Works hub.