W3C home > Mailing lists > Public > www-dom@w3.org > April to June 2013

Re: Resolving Futures w/multiple values

From: Tab Atkins Jr. <jackalmage@gmail.com>
Date: Tue, 23 Apr 2013 11:17:49 -0700
Message-ID: <CAAWBYDBn+ua8y-ccVnCUAHb1tACut=mjeqaYXeno7sy-8=BP-A@mail.gmail.com>
To: Dave Longley <dlongley@digitalbazaar.com>
Cc: "www-dom@w3.org" <www-dom@w3.org>, Anne van Kestern <annevk@annevk.nl>, Alex Russell <slightlyoff@chromium.org>
On Tue, Apr 23, 2013 at 11:10 AM, Dave Longley
<dlongley@digitalbazaar.com> wrote:
> Hi,
>
> I had a short discussion with Anne van Kesteren on #whatwg about the
> usefulness of allowing multiple values to be passed to the FutureResolver's
> resolve() method (see: http://dom.spec.whatwg.org/#futureresolver). We
> agreed it was worth exploring so I'm forwarding the idea on.
>
> This issue came up because I noticed that it can be difficult to wrap some
> existing node.js libraries with a Futures/Promises API. It is a fairly
> common practice in node.js to pass multiple values to callbacks when
> asynchronous operations complete. This behavior is even supported by popular
> code-flow utility libraries (see:
> https://github.com/caolan/async#waterfall). Unfortunately, the current
> Futures API does not easily support wrapping node.js APIs that exhibit this
> behavior because its resolve() and accept() methods only take one argument.
> This distinction can be overcome in some cases by a simple wrapper that
> passes all of the arguments as an array so they represent a single value.
> But there are also cases where this is insufficient:
>
> Consider this node.js async operation:
>
> foo(param1, param2, callback)
>
> When it completes, it calls:
>
> callback(err, bar, baz)
>
> In order to convert this continuation-passing style API to a Future, a
> wrapper creates a new function that wraps the async operation and passes a
> callback that will call reject() if a non-null 'err' parameter is defined
> and resolve() with an array containing both 'bar' and 'baz' otherwise. The
> code to use such a wrapper and its resulting Future might look like:
>
> futureFoo = wrap(foo);
> futureFoo(param1, param2).done(function(value) {/*value is [bar, baz]*/},
> function(err) {})
>
> This will be a bit odd for anyone used to using the library, but it is at
> least usable, unless 'bar' can be either an array or an object and 'baz' is
> optional. Then the results are indeterminate. This problem could be avoided
> by allowing Futures to be resolved to one or more values and passing them
> via resolve (or accept) as a typical argument list:
>
> resolve(value1, value2)
>
> This would allow developers to more easily wrap existing node.js libraries,
> which would be particularly useful for those whom write code that runs on
> both the server and the client. It would also permit them to continue using
> a stylistic choice that has been adopted in the node.js community.
>
> I think it's worth exploring whether or not this would be a useful addition
> to the Futures API -- and what the drawbacks may be. If compatibility with
> existing Promises/Futures libraries won't be too greatly harmed, or if this
> issue is deemed more important than some inconsistency with those existing
> libraries, then I would recommend that this behavior be supported. It would,
> in my opinion, aid in getting Futures more widely-adopted as it's one less
> barrier standing in the way of developers.

I think I like this behavior.  It also makes it easier to extend
things in the future, if they were originally created with a single
simple argument.

Since you can only return a single value from JS functions, though,
and thus by default any .then() functions must resolve to only a
single value, this definitely means that we need some sugar for
creating an already-accepted Future out of a value, so you can do
"return Future.of(a,b,c);" to pass three arguments to the next
callback in the chain.

~TJ
Received on Tuesday, 23 April 2013 18:18:37 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 20 October 2015 10:46:20 UTC