Skip to content

Cancel every promise in the chain, or only the deepest cancellable ancestor? #10

Open
@bergus

Description

@bergus

When I cancel a chain of promises, how do error handlers work?

We'll assume automatic propagation of the cancellation to parent promises, regardless how it's implemented. Let's have a

var cancellable = parentCancellable.then(doSomething, handleSomething);

Now when I call cancellable.cancel() (or whatever we use to signal cancellation), then parentCancellable will be rejected with a CancellationError. But what happens to cancellable? Is it supposed to be rejected with the same error? Or does its fate depend on the result of handleSomething() (which is required to be called by the A+spec)? Both options have their problems:

reject it:

  • what happens to all the error handlers in the chain? All of them are executed, but their results are ignored.
  • re-thrown (mutated?) exceptions, or wrapped (new) exceptions, are ignored instead of bubbling up the chain (all the result promises are already rejected). This creates a lot of unhandled rejections.
  • fulfillment values are created, but cannot be used. Returning a child promise from the handler might even leave dangling asynchronous jobs hang around. Do they need to be instantly cancelled as well? Still, even creating them is unnecessary overhead.

Sure, no handler that cannot deal with a CancellationError should be executed at all, but my hunch says the only the fewest catch clauses involve typechecking.

let errors bubble as usual:

  • Can lead to very odd behaviour. Do I really need to call .cancel() multiple (indefinite?) times to be sure that a chain of promise actions has been completely aborted?
  • I would expect a (pending) promise (that I "own", of which I know that there are no other listeners waiting for) to never fulfill after I have called .cancel() on it. Is this the use case that we need .fork() for, and such a method needs to give this guarantee, not (.then(null)).cancel() itself?
    Draft A #2 Draft A seems to work around this by introducing the cancelled state, which locks the promise in a pending-like state that guarantees that no handlers will ever be called. However, such will jeopardize proper working of .finally() and similar, and make .oncancelled handlers or cancel progress events necessary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions