W3C home > Mailing lists > Public > public-script-coord@w3.org > April to June 2013

Re: Future cancellation

From: Jonas Sicking <jonas@sicking.cc>
Date: Wed, 1 May 2013 00:16:06 -0700
Message-ID: <CA+c2ei_PYmNEFQbLcyzSvJLA-rNBPBNXKkH_myhZ0Hs78dO--w@mail.gmail.com>
To: Domenic Denicola <domenic@domenicdenicola.com>
Cc: Kevin Gadd <kevin.gadd@gmail.com>, Ron Buckton <rbuckton@chronicles.org>, "public-script-coord@w3.org" <public-script-coord@w3.org>, es-discuss <es-discuss@mozilla.org>
On Tue, Apr 30, 2013 at 10:01 PM, Domenic Denicola
<domenic@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
Received on Wednesday, 1 May 2013 07:17:04 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:37:49 UTC