- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Tue, 23 Apr 2013 11:17:49 -0700
- 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