Async functions not friendly to promise extensions

Async functions not friendly to promise extensions

This post was updated on .

While Promise methods and functions are friendly for it's extensions (or even not direct extensions but just thenables), the async function will always normalize it's result to instance of Promise, even it's ExtendedPromise, e.g.:

That makes it cumbersome if we work with promise extensions. What was the reasoning behind such design?
If not thenables in general, the promise extensions I believe should be passed through (or copied via its constructor.resolve).

Re: Async functions not friendly to promise extensions

You seem to misunderstand what async functions do to be async. Your function has the same product as the following:

new Promise((acc, rej) => acc(extendedPromise))

A promise that resolves to a extendedPromise instance. By no means do async functions use the returned values as their way of determining what type of promise they are: that'd break when using multiple returns with different types.

type of var k cannot be determined when the promise is made, due to the timeout not yet having returned. Ahead-of-time determining of type is really impossible with unpure functions, which must be available in async functions (e.g. for fetch). You can wrap your async function call in a custom promise (which would have your desired result), changing promise instance class hierarchies on-the-fly would make promises much less deterministic than what they are now, and would​ introduce confusion: typeof k would change depending on how long your program has run.

I definitely would not expect that k in such case resolves with promise of type of randomPromiseSubtype, same as you never expect that `setTimeout(1000).then()`may resolve with different promise types.

Re: Async functions not friendly to promise extensions

Well, not necessarily. It may have been possible to make the promise the async function returns be of the same type as the first promise it encounters during the synchronous part of its execution (remember that execution is synchronous until the first `await` or `return`). E.g.:

```js

async function foo() {

console.log("This is the synchronous bit");

if (someCondition) {

await a();

} else {

await b();

}

return await c();

}

```

Assume `a` and `b` return different types of promises. *Conceptually* it would have been possible to make `foo` return a promise of the same type as the one returned by `a` if `someCondition` were true or the same type as `b`'s promise if `someCondition` were false. E.g., as though it were like this:

```js

function foo() {

console.log("This is the synchronous bit");

let p;

if (someCondition) {

p = a();

} else {

p = b();

}

return p.then(_ => c());

}

```

That's just not how it's defined in the proposal and upcoming 2017 spec. I don't know if there's some implementational reason that wasn't done, or a philosophical reason, or what. It would certainly be more complex to implement and understand than what's been specified; I'm not surprised simplicity won out.

(Missing a callback there.) In that situation, in our alternate universe where async functions did what medikoo wants, the function would return a promise created by `NewPromiseCapability(%Promise%)`, since the function had to generate its own promise due to awaiting a synchronous function. E.g., the first promise it encountered in its synchronous code would be (effectively) `Promise.resolve(window.setTimeout(callback, 1000))`.

I'm not trying to suggest I think it would have been better. I like simplicity. But I do see what medikoo is getting at, and conceptually I'm not immediately seeing why it *couldn't* have been done that way instead.

type of var k cannot be determined when the promise is made, due to the timeout not yet having returned. Ahead-of-time determining of type is really impossible with unpure functions, which must be available in async functions (e.g. for fetch). You can wrap your async function call in a custom promise (which would have your desired result), changing promise instance class hierarchies on-the-fly would make promises much less deterministic than what they are now, and would​ introduce confusion: typeof k would change depending on how long your program has run.

Re: Async functions not friendly to promise extensions

I can't seem to find the exact issue, but I recall V8 wishing they
could single out native Promises for this proposed change (which is
really more of an optimization than a feature), but it ultimately got
rejected for consistency reasons I think.

>> ...that'd break when using multiple returns with different types.
>
> Well, not necessarily. It may have been possible to make the promise the
> async function returns be of the same type as the first promise it
> encounters during the synchronous part of its execution (remember that
> execution is synchronous until the first `await` or `return`). E.g.:
>
> ```js
> async function foo() {
> console.log("This is the synchronous bit");
> if (someCondition) {
> await a();
> } else {
> await b();
> }
> return await c();
> }
> ```
>
> Assume `a` and `b` return different types of promises. *Conceptually* it
> would have been possible to make `foo` return a promise of the same type as
> the one returned by `a` if `someCondition` were true or the same type as
> `b`'s promise if `someCondition` were false. E.g., as though it were like
> this:
>
> ```js
> function foo() {
> console.log("This is the synchronous bit");
> let p;
> if (someCondition) {
> p = a();
> } else {
> p = b();
> }
> return p.then(_ => c());
> }
> ```
>
> That's just not how it's defined in the proposal and upcoming 2017 spec. I
> don't know if there's some implementational reason that wasn't done, or a
> philosophical reason, or what. It would certainly be more complex to
> implement and understand than what's been specified; I'm not surprised
> simplicity won out.
>
> Re:
>
>> var k = (async function() {await window.setTimeout(1000); return
>> randomPromiseSubtype})();
>
> (Missing a callback there.) In that situation, in our alternate universe
> where async functions did what medikoo wants, the function would return a
> promise created by `NewPromiseCapability(%Promise%)`, since the function had
> to generate its own promise due to awaiting a synchronous function. E.g.,
> the first promise it encountered in its synchronous code would be
> (effectively) `Promise.resolve(window.setTimeout(callback, 1000))`.
>
> I'm not trying to suggest I think it would have been better. I like
> simplicity. But I do see what medikoo is getting at, and conceptually I'm
> not immediately seeing why it *couldn't* have been done that way instead.
>
> -- T.J. Crowder
>
> On Fri, Apr 14, 2017 at 11:53 AM, Matthias welp <[hidden email]> wrote:
>>
>> > I hope this explains it a bit for you.
>>
>> Sorry, but it didn't explain much. What to you mean by "that'd break when
>> using multiple returns with different types" ? Can you throw some simple
>> example?
>>
>>
>> sure
>>
>> var k = new Promise((acc, rej) => window.setTimeout(1000, ()=>
>> acc(randomPromiseSubtype)));
>>
>> ~=
>>
>> var k = (async function() {await window.setTimeout(1000); return
>> randomPromiseSubtype})();
>>
>> type of var k cannot be determined when the promise is made, due to the
>> timeout not yet having returned. Ahead-of-time determining of type is really
>> impossible with unpure functions, which must be available in async functions
>> (e.g. for fetch). You can wrap your async function call in a custom promise
>> (which would have your desired result), changing promise instance class
>> hierarchies on-the-fly would make promises much less deterministic than what
>> they are now, and would introduce confusion: typeof k would change depending
>> on how long your program has run.
>>
>>
>> _______________________________________________
>> 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>