- From: David Sheets <kosmo.zb@gmail.com>
- Date: Sat, 27 Apr 2013 17:55:33 +0100
- To: Ron Buckton <rbuckton@chronicles.org>
- Cc: David Bruant <bruant.d@gmail.com>, "Tab Atkins Jr." <jackalmage@gmail.com>, es-discuss <es-discuss@mozilla.org>, "Mark S. Miller" <erights@google.com>, "public-script-coord@w3.org" <public-script-coord@w3.org>, Mark Miller <erights@gmail.com>, Dean Tribble <tribble@e-dean.com>
On Sat, Apr 27, 2013 at 5:21 PM, Ron Buckton <rbuckton@chronicles.org> wrote:
> Here is a case where flattening helps:
>
> function executeAndWaitForComplete(command) {
> return getJSON(commandUrl + command)
> .then(function (commandResult) {
> if (commandResult.complete) {
> return commandResult.model;
This gets automatically lifted into Future, resulting in Future<typeof
commandResult.model>.
> }
> var statusUrl = commmandResult.statusUrl;
> return pollForCommandComplete(statusUrl);
This is always a Future and becomes the result of
executeAndWaitForComplete with type Future<typeof
commandResult.model>.
> })
> }
>
> function pollForCommandComplete(statusUrl) {
> return new Future(function(resolver) {
> var poll = function (pollResult) {
> if (pollResult.done) {
> resolve.resolve(pollResult.model);
> }
> else {
> setTimeout(function() {
> getJSON(statusUrl).done(poll, resolver.reject);
> }, 500);
> }
> }
> getJSON(statusUrl).done(poll, resolver.reject);
> });
> }
>
> In this example, the server will receive a command from the client and will
> process it asynchronously. The client then needs to poll an endpoint to
> check for completion of the command. Just using Futures, flattening is
> helpful here. Without flattening, executeAndWaitForComplete would could
> return either a Future<object> OR return a Future<Future<object>>.
I think the major point of confusion in these discussions is the
result of the framing of the discussion in terms of "flattening". I
believe most beneficial viewpoint is that of "autolifting".
That is, the exceptional case is not when the function argument of
"then" returns a Future+ that gets "flattened" but rather when the
function argument of "then" returns a non-Future that gets
automatically lifted into a Future.
This change in perspective is non-obvious because in many of these
APIs there is no succinct lifting operation to make a Future from
another value. This is a major reason why something like Future.of
(Future.accept) is important.
> In a non
> flattening world, the developer would have to change the function to:
>
> function executeAndWaitForComplete(command) {
> return new Future(function(resolver) {
> getJSON(commandUrl + command)
> .done(function (commandResult) {
> if (commandResult.complete) {
> resolver.resolve(commandResult.model);
> }
> var statusUrl = commmandResult.statusUrl;
> pollForCommandComplete(statusUrl).done(resolver.resolve,
> resolver.reject);
> }, resolver.reject)
> });
> }
In a non-flattening (and non-autolifting) world, this would be the code:
function executeAndWaitForComplete(command) {
return getJSON(commandUrl + command)
.then(function (commandResult) {
if (commandResult.complete) {
return Future.accept(commandResult.model);
}
var statusUrl = commmandResult.statusUrl;
return pollForCommandComplete(statusUrl);
})
}
The only difference here is that commandResult.model is explicitly
wrapped. This is because the signature of then is actually Future<a>
-> (a -> Future<b>) -> Future<b>.
David
Received on Saturday, 27 April 2013 16:57:28 UTC