whenCancelled method
Registers callback for cancellation and returns an unregister function.
Calls it once, synchronously, with the Cancelled when the job accepts a
cancellation, without waiting for the body; a refused cancellation does
not call it, and a job that ends Done or Failed releases it uncalled.
Registering does not observe a Failed outcome. The callback is
synchronous: its error goes to JobObserver.onError and on to the
answer, and the future of an async one is not awaited, nor are its
errors caught here.
final unregister = job.whenCancelled((cancelled) {
print(cancelled.reason);
});
// When the listener is no longer needed:
unregister();
See Listening for the cancellation on the outcomes page for when the callback runs and where its errors go.
Implementation
@override
void Function() whenCancelled(void Function(Cancelled) callback) {
final guarded = _guardListener(callback);
// `_cancelled` and not `_pendingCancel`: between the mark and the pass
// that tells the listeners there is a window -- the cascade onto the
// children -- and a registration made in there belongs in that pass,
// not ahead of it.
// Calling it on the spot would run it before everyone who registered
// earlier and is still waiting. Once the pass has run, `_cancelled` is
// set and a late registration is called at once, as promised; a job
// that finished cancelled set it on the way out.
final cancelled = _cancelled;
if (cancelled != null) {
guarded(cancelled);
return () {};
}
// Only a job that finished without a cancellation has nothing left to
// tell. One that finished cancelled and has not told its listeners yet
// -- `finished` and `onFinish` run first, and for a job dropped before
// its start there was no mark to set `_cancelled` earlier -- still has
// the pass ahead of it, and this registration belongs in it.
if (isFinished && _outcome is! Cancelled) return () {};
return _cancelListeners.add(guarded);
}