The ‘await’ keyword in C# is paired with a special function declaration 
(similar to function* as proposed for ES6) that can be used in one of three 
ways:

async void Foo() { ... }
async Task Foo() { ... }
async Task<T> Foo() { ... }

The ‘async’ keyword here flags the method for special case handing by the 
compiler to turn the function body into a state machine.  The kind of state 
machine generated is based on the return type of the method signature.

The “async void” method creates a state machine that inherently throws any 
unhandled exception to the UnhandledException trap/event of the AppDomain.  
This is often useful for a “fire-and-forget” operation where the caller is not 
concerned with the result.  An “async void" method cannot be awaited by the 
caller as it has no return type.

The “async Task” method signature creates a state machine that returns a Task 
(nee Future) that will eventually signal the successful completion or the 
exception thrown by the function.  It is roughly analogous to a “void” method 
signature as it has no result, and the Task is only used for further “await” 
expressions or defining continuations using .ContinueWith (analog to 
Future#then).  As the method returns a Task, any exception from the method will 
not be thrown to the AppDomain and therefore should be “await”ed appropriately 
(alternatively, the Task.Wait() method can be called that will block the 
current thread until the task completes and will throw any unhandled 
exceptions).

The “async Task<T>” method signature creates a state machine that returns a 
Task<T> that will provide either the eventual return value (of type T) or throw 
the exception. As with “async Task”, the exception must be explicitly handled 
by the caller either through an “await”, ContinueWith, or Wait.

Providing a special syntax for an ES function (either function* or function^) 
only goes half way to solving the issues of supporting “await”, as it would 
require some additional special ​effort to handle Future swallowing or bubbling 
the exception.

I have been experimenting with an (unofficial & unsupported) fork of TypeScript 
that supports ES6 generators by transpiling into a state machine in the 
function body. Albeit slower than a native implementation, it allows for some 
experimentation with the syntax in any ES5 compatible browser.  TypeScript has 
the advantage of static type checking during compile time, which allows me to 
mimic the C# behavior for the “async” keyword. As such I also have been 
experimenting with adding async/await to TypeScript and early indicators show 
that its is a very convenient way of handling asynchronous development flows. 
An example of a async method in this implementation looks something like:

class AuthAPI {
    async getAuthProvidersAsync(): Promise {
        var providers = await HttpRequestAsync.get(acsUrl, settings);
        return JSON.parse(providers);
    }
}

class AuthView {
    providers = ko.observableArray();
    async load(): void {
        var authAPI = new AuthAPI();
        var providers = <IAuthProvider[]>await authAPI.getAuthProvidersAsync();
        this.providers(providers);
    }
}

As opposed to the non-await implementation (with Futures/Promises):

class AuthAPI {
    getAuthProvidersAsync(): Promise {
        return HttpRequestAsync.get(acsUrl, settings)
            .then(p => JSON.parse(p));
    }
}

class AuthView {
    providers = ko.observableArray();
    load(): void {
        var authAPI = new AuthAPI();
        authAPI.done((providers: IAuthProvider[]) => {
            this.providers(providers);
        });
    }
}

While this example may not show a lot of power, imagine an async polling 
mechanism:

class AppAPI {
   async waitFor(eventId: string): Promise {
     while (true) {
         var result = await HttpRequestAsync.get(eventUri + “?eventId=” + 
eventId);
         var obj = JSON.parse(result);
         if (obj.complete) {
             return obj.url;
         }
         await Promise.sleep(500);
     }
   }
}

Writing that using then is much more cumbersome:

class AppAPI {
    waitFor(eventId: string): Promise {
      return new Promise(resolver => {
        var awaiter = () => {
            HttpRequestAsync.get(eventUri + “?eventId=” + eventId).done(result 
=> {
                try {
                    var obj = JSON.parse(result);
                    if (obj.complete) {
                        resolver.resolve(obj.url);
                        return;
                    }
                    setTimeout(awaiter, 500);
                }
                catch (e) {
                    resolver.reject(e);
                }
            }, resolver.reject);
            awaiter();
        }
      });
    }
}

Adding “await” would be a valuable addition to the language, assuming we can 
solve the “swallowed exception” issues, or at least call out that it is a 
caveat to developers that should be handled explicitly.

Another way to get async/await-like capabilities might be to combine the 
Q.async/task.spawn and yield functionality with something like Python-style 
decorators. I’ve been working on a proposal for decorators for both TypeScript 
and ES (and have another unofficial/experimental fork of TypeScript with 
support for this up on CodePlex today).  If that were the case, you could fake 
async/await without having to directly wrap the function call as is necessary 
for Q.async/task.spawn today:

class Foo {
    // example decorator using Python-style syntax (@ token may collide with 
symbols/private)
    @async myAsync() {
        var a = yield myOtherAsync();
    }
}

Ron

Sent from Windows Mail

From: Dean Landolt
Sent: ‎Tuesday‎, ‎April‎ ‎23‎, ‎2013 ‎6‎:‎28‎ ‎AM
To: David Bruant
Cc: Brendan Eich, Mark S. Miller, Douglas Crockford, 
[email protected], Norbert Lindenberg, Markus Lanthaler, EcmaScript




On Tue, Apr 23, 2013 at 9:12 AM, David Bruant 
<[email protected]<mailto:[email protected]>> wrote:
Le 23/04/2013 14:56, Dean Landolt a écrit :
On Tue, Apr 23, 2013 at 4:54 AM, David Bruant 
<[email protected]<mailto:[email protected]>> wrote:
Le 22/04/2013 19:32, Dean Landolt a écrit :

I was just saying there will be pressure to include support for thenables 
(already in DOMFutures). If you believe otherwise don't let me dissuade you -- 
I would absolutely love it if I were proven wrong!
I guess it would take making sure no content can be confused by the current 
steps 3-5 of the current resolve spec [1]. I believe browser vendors have tools 
to study this kind of things.

CasperJS [2] create objects with a then method [3]. Interestingly, this doesn't 
run in the browser (until someone decides to re-implement it of top of a web 
browser or FirefoxOS. [4] ?). Potentially more interestingly, Casper objects 
could be promises subclasses (to be considered).
It wouldn't be surprising if there were content on the web where the promise 
subclass trick couldn't work.


What do you mean by the promise subclass trick? If you mean that Casper 
instances would subclass Promise I don't think that'd work out too well as is. 
Promises/A (and I presume A+) intentionally specified `then` to return a new 
promise, so Casper would have to change in a very breaking way to pull this off.
I'm not sure it would be a breaking change for the vast majority of people. 
They may actually like that instead of being forced to to casper.start. They 
may also enjoy being able to chain .then-s. But maybe it's breaking.

IIRC you can already chain thens -- the break is that you will be forced to 
chain thens in order to maintain your intended chronology. Inheriting from 
Promise would suggest all those then calls will be fired in parallel instead of 
happening in serial.

Although the only time I tried Casper (~ a year ago) I gave up on it because I 
couldn't get this stuff right anyway.

Anyway, my point was that there exist libraries in which "then" is a function 
and the object with this function isn't a promise. These libraries will end up 
in a terrible confusion when used with Futures.
You think you're resolving a future with an object and... oops! the built-in 
Future algorithm confused your object for a promise. Suddenly, not only are you 
not resolving your promise with the value, but your .then method is called 
unexpectedly.

Apologies, I wasn't very clear. I completely agree with this point and was just 
trying to reinforce it :)


In any case, considering that an object with a 'then' function is a promise is 
a recipe for confusion. Promise/A+ folks asked for and are happy about it. The 
rest of the webdevs who aren't aware of this subtle non-intuitive rule will 
have a very hard time when, for whatever reason, they have a 'then' function in 
a resolve value and their code really behaves in a way they don't understand.


I agree it's a recipe for confusion. But the weight of legacy code (growing by 
the day) may be too much to bear.
What about the weight of legacy non-promise code using "then"? The best thing 
we can say now is that we know nothing about it and it'd be wise to wait until 
more data on "then" is available. The Casper example should at least worry us. 
I hope it will be the browser vendors choice.


Hopefully not -- it's really very simple for Promises/A+ libs to add `then` to 
the Promise prototype.
Aren't they already doing that? I don't understand your point here.

No, DOMFutures ships with this OOTB. If there were an es Promise or Future 
builtin I suspect there would be a lot of pressure to specify it with `then` on 
the prototoype to make its instances compatible with existing Promises/A+ libs. 
That's the crushing weight of legacy I'm referring to.

What occurred to me is that it really is just a few lines of code for each of 
these Promises/A+ libs to add to tack on the prototype `then` without having to 
muddy the spec. In hindsight this seems obvious. I wonder why DOMFutures didn't 
go this route? It may not be too late.


I don't think in the entire platform there is a precedent of doing this (maybe 
for a good reason?). We'll see what web browsers end up implementing.


IMHO __proto__ is one precedent -- and we know how that's going :P
Once again, __proto__ is not a good comparison. It's already in the platform. 
As far as promises are concerned, the platform has exactly no obligation to 
follow the current Future or an alternative that'll emerge tomorrow; no 
obligation to follow Promise/A+ or whatever else.

You said "I don't think in the entire platform there is a precedent of doing 
this". I assume by "this" you meant using a forgeable string key that could 
lead to confusion. That is what we were discussing, right? If so I think 
__proto__ is a great example. And again, I think it helps make your (our) point 
:)

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to