Future cancellation

Jonas Sicking jonas at sicking.cc
Wed May 1 00:16:06 PDT 2013


On Tue, Apr 30, 2013 at 10:01 PM, Domenic Denicola
<domenic at domenicdenicola.com> wrote:
> I think the .NET disposal analogy is a good one. I don’t know how other
> runtimes handle it, but in .NET you would dispose of a resource (perhaps
> representing an in-progress asynchronous operation) by having the handle for
> that resource implement IDisposable, i.e. have a dispose() method. So I
> think if you wanted to do something similar with promises, you’d return a
> disposable handle alongside your promise (i.e. `return { promise, diposable
> }` or simply `{ promise, dispose }`). You can also layer that on top of the
> promise (i.e. `promise.dispose = () => { .. }; return promise;`).

I don't see how the "layer on top" solution is different from
subclassing? In both cases you get an object which implements the
Future interface and additionally has a .cancel()/.dispose() method on
it. The only difference appears to be the name?

I don't really see the benefit of returning a { promise, dispose }
tuple as result comparsed to the layering/subclassing solution.

With the tuple approach, you get two objects one which represents the
operation and one which represents the result. The result object can
be composed with other promises or you simply register to wait for the
result. So something like:

{ promise, dispose } = doSomeOperation();
handleResult(promise);
cancelIfUserClicksAbort(dispose);

or

{ promise, dispose } = doSomeOperation();
cancelIfUserClicksAbort(dispose);
return promise;

or

{ promise, dispose } = doSomeOperation();
cancelIfUserClicksAbort(dispose);
promise.then(val => displayResult(val));


with the layering/subclassing approach you do essentially exactly the
same thing, except you use a single object rather than two:

cancelableFuture = doSomeOperation();
handleResult(cancelableFuture);
cancelIfUserClicksAbort(cancelableFuture);

or

cancelableFuture = doSomeOperation();
cancelIfUserClicksAbort(cancelableFuture);
return cancelableFuture;

or

cancelableFuture = doSomeOperation();
cancelIfUserClicksAbort(cancelableFuture);
cancelableFuture.then(val => displayResult(val));


However with this approach you get an API which automatically simply
works as an API returning a Future in case you don't need to abort the
operation or display its progress:

handleResult(doSomeOperation());
or
return doSomeOperation();
or
doSomeOperation().then(val => displayResult(val));

I.e. if you don't care about the operation part, the API simply works
as any other API which returns a promise. This seems like a very nice
thing. The only "cost" of this API is that it doesn't compose when you
compose the future, but neither does the dispose object in the tuple
approach.

/ Jonas


More information about the es-discuss mailing list