await on synchronous functions

classic Classic list List threaded Threaded
35 messages Options
12
Reply | Threaded
Open this post in threaded view
|

await on synchronous functions

Mark Volkmann
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

--
R. Mark Volkmann
Object Computing, Inc.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Kevin Smith
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Andrea Giammarchi-2
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Tom Van Cutsem-3
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Andrea Giammarchi-2
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Gil Tayar
In reply to this post by Tom Van Cutsem-3
I would tend to agree with Tom (i.e. Promisify non-promises), even though we should notice that awaiting a synchronous function adds a non-trivial overhead, because although the promise is immediately resolved, the await will "return" only after being processed in the event loop (if I remember the Promise spec correctly).

So if option #1 has the advantage of "alerting" us to this performance effect, why do I still prefer option #2? Because of consistency - this is similar to the callback the ".then" of a promise accepts: if the callback returns a promise, it is chained, and if it is a regular value, then it is promisified and chained. 

The same two options exist there, and the spec decided on #2. And rightfully so. I like the fact that the code "just works" and in languages like JS, I would prefer it "just working" than being "statically correct". Dynamic languages lots of time tend to prefer the "just works, albeit slowly" approach to the "theoretically and statically correct" approach. 

- Gil

On Fri, Jul 17, 2015 at 9:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



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




--
Yours,
Gil Tayar
Software Architect @ Wix

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Ben Newman
In reply to this post by Andrea Giammarchi-2
If we stick with the rule that await is only regarded as a keyword if it appears in the body of an async function, then await x without async is simply a syntax error, and we can avoid having to answer this question!

That said, perhaps a more natural way of handling wayward await expressions is to treat them as referring to the closest enclosing async function on the call stack (not necessarily the immediate enclosing function), throwing an exception if there is no async function on the stack. Then any await expression would delay the resolution of the Promise returned by whatever async function is currently executing. The same-function-body syntax restriction is a special case of that more general model (and notably easier to implement by transpiling to generators!).

Generalizing async/await in this way turns out to be equivalent to introducing coroutines into the language, and while I would love to see that happen one day (it would greatly simplify writing parallel forEach loops, for example), it would require substantial changes to the execution model of the language.

Here are some slides from a talk I gave earlier this year about the benefits and pitfalls of coroutines, in case you're interested: http://benjamn.github.io/goto2015-talk
On Fri, Jul 17, 2015 at 11:35 AM Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



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

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Mark Volkmann
In reply to this post by Andrea Giammarchi-2
I think this is a valid use case for await working with synchronous functions.
Suppose I have an array of functions that I want to call in series.
Some are marked async, some return a promise, and some do neither.
I'd like to be able to do something like this:

for (let fn of myFunctions) {
  let result = await fn();
  // Do something with result.
}

On Fri, Jul 17, 2015 at 1:35 PM, Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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




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




--
R. Mark Volkmann
Object Computing, Inc.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Chris Toshok
In reply to this post by Ben Newman
I think we're confusing two different cases here:

1) usage of `await` in the body of a function that is not itself marked as `async`
2) usage of `await f()` where `f` is not marked as `async`.

1 is easy to mark as an early error (and should be imo).  2, not so much (and is what Mark was asking?)

-c


On Fri, Jul 17, 2015 at 12:30 PM, Ben Newman <[hidden email]> wrote:
If we stick with the rule that await is only regarded as a keyword if it appears in the body of an async function, then await x without async is simply a syntax error, and we can avoid having to answer this question!

That said, perhaps a more natural way of handling wayward await expressions is to treat them as referring to the closest enclosing async function on the call stack (not necessarily the immediate enclosing function), throwing an exception if there is no async function on the stack. Then any await expression would delay the resolution of the Promise returned by whatever async function is currently executing. The same-function-body syntax restriction is a special case of that more general model (and notably easier to implement by transpiling to generators!).

Generalizing async/await in this way turns out to be equivalent to introducing coroutines into the language, and while I would love to see that happen one day (it would greatly simplify writing parallel forEach loops, for example), it would require substantial changes to the execution model of the language.

Here are some slides from a talk I gave earlier this year about the benefits and pitfalls of coroutines, in case you're interested: http://benjamn.github.io/goto2015-talk
On Fri, Jul 17, 2015 at 11:35 AM Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



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

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



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Mark Volkmann
Yes, I am asking about case #2. Thanks for clarifying Chris.
For what it's worth, Traceur allows this now.

On Fri, Jul 17, 2015 at 2:36 PM, Chris Toshok <[hidden email]> wrote:
I think we're confusing two different cases here:

1) usage of `await` in the body of a function that is not itself marked as `async`
2) usage of `await f()` where `f` is not marked as `async`.

1 is easy to mark as an early error (and should be imo).  2, not so much (and is what Mark was asking?)

-c


On Fri, Jul 17, 2015 at 12:30 PM, Ben Newman <[hidden email]> wrote:
If we stick with the rule that await is only regarded as a keyword if it appears in the body of an async function, then await x without async is simply a syntax error, and we can avoid having to answer this question!

That said, perhaps a more natural way of handling wayward await expressions is to treat them as referring to the closest enclosing async function on the call stack (not necessarily the immediate enclosing function), throwing an exception if there is no async function on the stack. Then any await expression would delay the resolution of the Promise returned by whatever async function is currently executing. The same-function-body syntax restriction is a special case of that more general model (and notably easier to implement by transpiling to generators!).

Generalizing async/await in this way turns out to be equivalent to introducing coroutines into the language, and while I would love to see that happen one day (it would greatly simplify writing parallel forEach loops, for example), it would require substantial changes to the execution model of the language.

Here are some slides from a talk I gave earlier this year about the benefits and pitfalls of coroutines, in case you're interested: http://benjamn.github.io/goto2015-talk
On Fri, Jul 17, 2015 at 11:35 AM Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



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

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



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




--
R. Mark Volkmann
Object Computing, Inc.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Ben Newman
In reply to this post by Chris Toshok
Having addressed (1) earlier, perhaps by mistake, my thought on (2) is that you probably want await f() to work the same way if f() just happens to return a Promise, as when f is actually async, but there is no way to know, in general, if some arbitrary function will or will not return a Promise, so await should treat all arguments in the same way: by calling Promise.resolve.

It's an open question whether a sufficiently smart runtime could optimize cases when the argument is not a Promise, or when the Promise is already resolved, but it would have to do so under the constraint of not revealing that optimization to the user.
On Fri, Jul 17, 2015 at 12:36 PM Chris Toshok <[hidden email]> wrote:
I think we're confusing two different cases here:

1) usage of `await` in the body of a function that is not itself marked as `async`
2) usage of `await f()` where `f` is not marked as `async`.

1 is easy to mark as an early error (and should be imo).  2, not so much (and is what Mark was asking?)

-c


On Fri, Jul 17, 2015 at 12:30 PM, Ben Newman <[hidden email]> wrote:
If we stick with the rule that await is only regarded as a keyword if it appears in the body of an async function, then await x without async is simply a syntax error, and we can avoid having to answer this question!

That said, perhaps a more natural way of handling wayward await expressions is to treat them as referring to the closest enclosing async function on the call stack (not necessarily the immediate enclosing function), throwing an exception if there is no async function on the stack. Then any await expression would delay the resolution of the Promise returned by whatever async function is currently executing. The same-function-body syntax restriction is a special case of that more general model (and notably easier to implement by transpiling to generators!).

Generalizing async/await in this way turns out to be equivalent to introducing coroutines into the language, and while I would love to see that happen one day (it would greatly simplify writing parallel forEach loops, for example), it would require substantial changes to the execution model of the language.

Here are some slides from a talk I gave earlier this year about the benefits and pitfalls of coroutines, in case you're interested: http://benjamn.github.io/goto2015-talk
On Fri, Jul 17, 2015 at 11:35 AM Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



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

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



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Mark Volkmann
Going back to my original question, suppose I write this:

for (let fn of myFunctions) {
  let result = await fn();
  // Do something with result.
}

If all the functions happen to be synchronous and take a while to complete, am I blocking the event loop?
I think what I'd like to happen is for each call to happen in the next pass through the event loop.

On Fri, Jul 17, 2015 at 2:44 PM, Ben Newman <[hidden email]> wrote:
Having addressed (1) earlier, perhaps by mistake, my thought on (2) is that you probably want await f() to work the same way if f() just happens to return a Promise, as when f is actually async, but there is no way to know, in general, if some arbitrary function will or will not return a Promise, so await should treat all arguments in the same way: by calling Promise.resolve.

It's an open question whether a sufficiently smart runtime could optimize cases when the argument is not a Promise, or when the Promise is already resolved, but it would have to do so under the constraint of not revealing that optimization to the user.

On Fri, Jul 17, 2015 at 12:36 PM Chris Toshok <[hidden email]> wrote:
I think we're confusing two different cases here:

1) usage of `await` in the body of a function that is not itself marked as `async`
2) usage of `await f()` where `f` is not marked as `async`.

1 is easy to mark as an early error (and should be imo).  2, not so much (and is what Mark was asking?)

-c


On Fri, Jul 17, 2015 at 12:30 PM, Ben Newman <[hidden email]> wrote:
If we stick with the rule that await is only regarded as a keyword if it appears in the body of an async function, then await x without async is simply a syntax error, and we can avoid having to answer this question!

That said, perhaps a more natural way of handling wayward await expressions is to treat them as referring to the closest enclosing async function on the call stack (not necessarily the immediate enclosing function), throwing an exception if there is no async function on the stack. Then any await expression would delay the resolution of the Promise returned by whatever async function is currently executing. The same-function-body syntax restriction is a special case of that more general model (and notably easier to implement by transpiling to generators!).

Generalizing async/await in this way turns out to be equivalent to introducing coroutines into the language, and while I would love to see that happen one day (it would greatly simplify writing parallel forEach loops, for example), it would require substantial changes to the execution model of the language.

Here are some slides from a talk I gave earlier this year about the benefits and pitfalls of coroutines, in case you're interested: http://benjamn.github.io/goto2015-talk
On Fri, Jul 17, 2015 at 11:35 AM Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



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

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



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




--
R. Mark Volkmann
Object Computing, Inc.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Ben Newman
Yep, all current implementations that I know of (Traceur, Babel/Regenerator, various other generator-based approaches) do what you want, because Promise.resolve(fn()).then(result => ...) always runs the callback a future turn of the event loop.

Please note I might not be using the term "turn" precisely here (microtask?); my point is just that your example would not be blocking the event loop, and that's a good thing!
On Fri, Jul 17, 2015 at 12:50 PM Mark Volkmann <[hidden email]> wrote:
Going back to my original question, suppose I write this:

for (let fn of myFunctions) {
  let result = await fn();
  // Do something with result.
}

If all the functions happen to be synchronous and take a while to complete, am I blocking the event loop?
I think what I'd like to happen is for each call to happen in the next pass through the event loop.

On Fri, Jul 17, 2015 at 2:44 PM, Ben Newman <[hidden email]> wrote:
Having addressed (1) earlier, perhaps by mistake, my thought on (2) is that you probably want await f() to work the same way if f() just happens to return a Promise, as when f is actually async, but there is no way to know, in general, if some arbitrary function will or will not return a Promise, so await should treat all arguments in the same way: by calling Promise.resolve.

It's an open question whether a sufficiently smart runtime could optimize cases when the argument is not a Promise, or when the Promise is already resolved, but it would have to do so under the constraint of not revealing that optimization to the user.

On Fri, Jul 17, 2015 at 12:36 PM Chris Toshok <[hidden email]> wrote:
I think we're confusing two different cases here:

1) usage of `await` in the body of a function that is not itself marked as `async`
2) usage of `await f()` where `f` is not marked as `async`.

1 is easy to mark as an early error (and should be imo).  2, not so much (and is what Mark was asking?)

-c


On Fri, Jul 17, 2015 at 12:30 PM, Ben Newman <[hidden email]> wrote:
If we stick with the rule that await is only regarded as a keyword if it appears in the body of an async function, then await x without async is simply a syntax error, and we can avoid having to answer this question!

That said, perhaps a more natural way of handling wayward await expressions is to treat them as referring to the closest enclosing async function on the call stack (not necessarily the immediate enclosing function), throwing an exception if there is no async function on the stack. Then any await expression would delay the resolution of the Promise returned by whatever async function is currently executing. The same-function-body syntax restriction is a special case of that more general model (and notably easier to implement by transpiling to generators!).

Generalizing async/await in this way turns out to be equivalent to introducing coroutines into the language, and while I would love to see that happen one day (it would greatly simplify writing parallel forEach loops, for example), it would require substantial changes to the execution model of the language.

Here are some slides from a talk I gave earlier this year about the benefits and pitfalls of coroutines, in case you're interested: http://benjamn.github.io/goto2015-talk
On Fri, Jul 17, 2015 at 11:35 AM Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



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

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



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




--
R. Mark Volkmann
Object Computing, Inc.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Mark S. Miller-2
In reply to this post by Mark Volkmann
Wait for the next turn/job or the event loop.

On Fri, Jul 17, 2015 at 10:09 AM, Mark Volkmann <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

--
R. Mark Volkmann
Object Computing, Inc.

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




--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Mark S. Miller-2
In reply to this post by Kevin Smith
On Fri, Jul 17, 2015 at 10:33 AM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?


Yes, absolutely. It must be equivalent to 
Promise.resolve(1).then(..success-continuation-of-await.., ..error-continuation-of-await..)
though of course for the original bindings of Promise.resolve and .then rather than the current bindings.


--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Mark S. Miller-2
In reply to this post by Andrea Giammarchi-2


On Fri, Jul 17, 2015 at 10:41 AM, Andrea Giammarchi <[hidden email]> wrote:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

Definitely #2. Had #1 been proposed, async/await never would have achieved consensus.
 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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




--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Mark S. Miller-2
In reply to this post by Andrea Giammarchi-2
Hi Andrea, what do you mean by "Promise must Promise"? I've never seen this phrase before.


On Fri, Jul 17, 2015 at 11:35 AM, Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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




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




--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Mark S. Miller-2
In reply to this post by Ben Newman


On Fri, Jul 17, 2015 at 12:30 PM, Ben Newman <[hidden email]> wrote:
If we stick with the rule that await is only regarded as a keyword if it appears in the body of an async function, then await x without async is simply a syntax error, and we can avoid having to answer this question!

Two more possible contexts:

* We've talked about allowing await at the top level of modules, I think so that the await continuation could proceed after the synchronous part of the load. I am unclear on the details and cannot reconstruct a sensible story from memory.

* Jafar and I will be making a proposal for allowing await within function* generator functions. No need to debate this until we make the proposal, but it does not alter what await would do inside an async function.

 

That said, perhaps a more natural way of handling wayward await expressions is to treat them as referring to the closest enclosing async function on the call stack (not necessarily the immediate enclosing function), throwing an exception if there is no async function on the stack.

This would have the same hazards as deep generators: Intermediate functions on the call stack could be postponed till later turns/jobs without their knowledge, causing violations of their assumptions. The event-loop model makes strong guarantees about possible interleaving. We defined generators and async functions as shallow to preserve those guarantees.

 
Then any await expression would delay the resolution of the Promise returned by whatever async function is currently executing. The same-function-body syntax restriction is a special case of that more general model (and notably easier to implement by transpiling to generators!).

Generalizing async/await in this way turns out to be equivalent to introducing coroutines into the language,

Exactly! Same think for deep generators. That's why we must not do either.

 
and while I would love to see that happen one day (it would greatly simplify writing parallel forEach loops, for example), it would require substantial changes to the execution model of the language.

Here are some slides from a talk I gave earlier this year about the benefits and pitfalls of coroutines, in case you're interested: http://benjamn.github.io/goto2015-talk

I'll take a look. But I've already looked at fibers themselves and rejected them on this basis.

 
On Fri, Jul 17, 2015 at 11:35 AM Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



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

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




--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Mark S. Miller-2
In reply to this post by Mark Volkmann
I would expect any implementation to do #2 since that's what the draft spec says.


On Fri, Jul 17, 2015 at 12:40 PM, Mark Volkmann <[hidden email]> wrote:
Yes, I am asking about case #2. Thanks for clarifying Chris.
For what it's worth, Traceur allows this now.

On Fri, Jul 17, 2015 at 2:36 PM, Chris Toshok <[hidden email]> wrote:
I think we're confusing two different cases here:

1) usage of `await` in the body of a function that is not itself marked as `async`
2) usage of `await f()` where `f` is not marked as `async`.

1 is easy to mark as an early error (and should be imo).  2, not so much (and is what Mark was asking?)

-c


On Fri, Jul 17, 2015 at 12:30 PM, Ben Newman <[hidden email]> wrote:
If we stick with the rule that await is only regarded as a keyword if it appears in the body of an async function, then await x without async is simply a syntax error, and we can avoid having to answer this question!

That said, perhaps a more natural way of handling wayward await expressions is to treat them as referring to the closest enclosing async function on the call stack (not necessarily the immediate enclosing function), throwing an exception if there is no async function on the stack. Then any await expression would delay the resolution of the Promise returned by whatever async function is currently executing. The same-function-body syntax restriction is a special case of that more general model (and notably easier to implement by transpiling to generators!).

Generalizing async/await in this way turns out to be equivalent to introducing coroutines into the language, and while I would love to see that happen one day (it would greatly simplify writing parallel forEach loops, for example), it would require substantial changes to the execution model of the language.

Here are some slides from a talk I gave earlier this year about the benefits and pitfalls of coroutines, in case you're interested: http://benjamn.github.io/goto2015-talk
On Fri, Jul 17, 2015 at 11:35 AM Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



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

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



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




--
R. Mark Volkmann
Object Computing, Inc.

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




--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: await on synchronous functions

Mark S. Miller-2
In reply to this post by Ben Newman


On Fri, Jul 17, 2015 at 12:44 PM, Ben Newman <[hidden email]> wrote:
Having addressed (1) earlier, perhaps by mistake, my thought on (2) is that you probably want await f() to work the same way if f() just happens to return a Promise, as when f is actually async, but there is no way to know, in general, if some arbitrary function will or will not return a Promise, so await should treat all arguments in the same way: by calling Promise.resolve.

It's an open question whether a sufficiently smart runtime could optimize cases when the argument is not a Promise, or when the Promise is already resolved, but it would have to do so under the constraint of not revealing that optimization to the user.

Exactly. And thanks for pointing it out. Specs traffic only in observable differences. In those rare circumstances when an implementation knows that there's no observable difference between .then and .asap, it can optimize. But only then.

 

On Fri, Jul 17, 2015 at 12:36 PM Chris Toshok <[hidden email]> wrote:
I think we're confusing two different cases here:

1) usage of `await` in the body of a function that is not itself marked as `async`
2) usage of `await f()` where `f` is not marked as `async`.

1 is easy to mark as an early error (and should be imo).  2, not so much (and is what Mark was asking?)

-c


On Fri, Jul 17, 2015 at 12:30 PM, Ben Newman <[hidden email]> wrote:
If we stick with the rule that await is only regarded as a keyword if it appears in the body of an async function, then await x without async is simply a syntax error, and we can avoid having to answer this question!

That said, perhaps a more natural way of handling wayward await expressions is to treat them as referring to the closest enclosing async function on the call stack (not necessarily the immediate enclosing function), throwing an exception if there is no async function on the stack. Then any await expression would delay the resolution of the Promise returned by whatever async function is currently executing. The same-function-body syntax restriction is a special case of that more general model (and notably easier to implement by transpiling to generators!).

Generalizing async/await in this way turns out to be equivalent to introducing coroutines into the language, and while I would love to see that happen one day (it would greatly simplify writing parallel forEach loops, for example), it would require substantial changes to the execution model of the language.

Here are some slides from a talk I gave earlier this year about the benefits and pitfalls of coroutines, in case you're interested: http://benjamn.github.io/goto2015-talk
On Fri, Jul 17, 2015 at 11:35 AM Andrea Giammarchi <[hidden email]> wrote:
Think about a large program where you refactor a single async function to no longer be async

did that ever happened in the history of logic? I am actually curious to understand a single valid case where that would be a solution to any problem.

Apologies if I can't see your point but we've been talking about "Promise must Promise" so much this answer was absolutely unexpected.

Thanks for any sort of clarification

On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem <[hidden email]> wrote:
2015-07-17 19:41 GMT+02:00 Andrea Giammarchi <[hidden email]>:
If I might, if there's one thing that has never particularly shone in JS, that is consistency.

I see only two possibilities here: 1) it throws with non Promises 2) it "Promisify" anything that's not a Promise as if it was a `Promise.resolve(1)` ... but since there's too much magic in the second point, I'd rather stick with the first one.

I would be highly in favor of (2). Think about a large program where you refactor a single async function to no longer be async. Then I see no reason why I should be forced to refactor all of its callers to remove the await keyword. Going from sync to async requires refactoring because you're introducing new potential interleaving hazards, but any code that is already prepared to work with async functions (or promises in general) should work equally fine on immediately resolved promises.

regards,
Tom

 

Just my quick thoughts

Best Regards

On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith <[hidden email]> wrote:
I know the spec for this isn't finalized, but what is the current direction for the behaviour when await is used on a function that is not marked async and doesn't return a Promise? Should it run immediately or wait for the next turn of the event loop?

More generally, the question is: what should await do for non-promises?

    await 1;

Should it force a job to be queued?

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



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



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

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



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




--
    Cheers,
    --MarkM

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