Async functions not friendly to promise extensions
resend/fwd of accidental personal reply
Hello Medikoo,
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.
I hope this explains it a bit for you.
-Matthias
On 14 Apr 2017 09:58, "medikoo" <medikoo+mozilla.org at medikoo.com> wrote:
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.: class ExtendedPromise extends Promise {}; var extendedPromise = new ExtendedPromise(function (resolve) { resolve(); }); extendedPromise.then().constructor === ExtendedPromise // true var asyncFn = async function () { return extendedPromise; }; asyncFn().constructor === ExtendedPromise // false asyncFn().constructor === Promise // true 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).
View this message in context: Async functions not friendly to promise extensions mozilla.6506.n7.nabble.com/Async-functions-not-friendly-to-promise-extensions-tp364921.html
Sent from the Mozilla - ECMAScript 4 discussion mailing list archive mozilla.6506.n7.nabble.com/Mozilla-ECMAScript-4-discussion-f89340.html
at Nabble.com.
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))
Yes, I totally understand that, and it's clear to me that it's that way. In my post I question that design, as it seems to me that way nicer would be if it's as follows:
If (isThenable(result)) return result; else return new Promise((resolve, reject) => resolve(result));
Or if above seems too liberal, then at least:
if (isPromise(result)) return new result.constructor((resolve, reject) =>
resolve(result)); else return new Promise((resolve, reject) => resolve(result));
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.
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?
-- View this message in context: mozilla.6506.n7.nabble.com/Async-functions-not-friendly-to-promise-extensions-tp364921p364924.html Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.
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.
var k = (async function() {await window.setTimeout(1000); return
randomPromiseSubtype})();
Assuming that setTmeout(1000) returns a promise, this code is equivalent to:
async function() { return setTimeout(1000).then(function () { return randomPromiseSubtype; }); };
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.
However if it's:
async function() { return randomPromiseSubtypeTimeout(1000).then(function () { return whateverPromise; }); };
It'll be great if k resolves with promise that shares the constructor with promise returned by randomPromiseSubtypeTimeout(1000).then(...). That's my point
-- View this message in context: mozilla.6506.n7.nabble.com/Async-functions-not-friendly-to-promise-extensions-tp364921p364926.html Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.
...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.:
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:
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
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.
Google's failing me on finding this, though, or I would link my source here.
Isiah Meadows me at isiahmeadows.com
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.:
class ExtendedPromise extends Promise {};
var extendedPromise = new ExtendedPromise(function (resolve) { resolve(); });
extendedPromise.then().constructor === ExtendedPromise // true
var asyncFn = async function () { return extendedPromise; };
asyncFn().constructor === ExtendedPromise // false
asyncFn().constructor === Promise // true
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).
-- View this message in context: mozilla.6506.n7.nabble.com/Async-functions-not-friendly-to-promise-extensions-tp364921.html Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.