kneden
kneden copied to clipboard
Unnecessary extra tick
var foo = async () => {
console.log(1);
return (await 1) + 2;
}
foo();
console.log(2);
should transpile to:
var foo = function foo() {
return new Promise(function (resolve) {
console.log(1);
resolve(1);
}).then(function (_resp) {
return _resp + 2;
});
};
foo();
console.log(2);
which should log 1, then 2.
but instead transpiles to:
var foo = function foo() {
return Promise.resolve().then(function () {
console.log(1);
return 1;
}).then(function (_resp) {
return _resp + 2;
});
};
foo();
console.log(2);
This difference means the async function takes an extra tick - which results in logging 2, then 1.
Nice find, thanks for reporting.
There is the edge case of what to do with functions thrown before an await statement to take into account. It's some time ago I looked it up in the spec, but I think the correct behaviour is to make these too reject the promise instead of returning an error. That would make the total code required be something like this instead:
const PromiseChainStart = {
then(func) {
return new Promise(function (resolve, reject) {
try {
resolve(func());
} catch (err) {
reject(err);
}
});
}
};
PromiseChainStart.then(function () {}
});
Doing it that way would also keep the code generation easier since there wouldn't be two return styles to handle (resolve/reject calls vs. return/throw).
@marten-de-vries it should reject the promise, and new Promise
already has a try/catch, so no explicit one is needed.
I hadn't really thought of these semantics before, but curious: should 1 log before 2 if you aren't awaiting foo
's call? I guess said another way, should there be a difference in logging the values if the code is:
foo();
console.log(2);
versus:
await foo();
console.log(2);
Apologies if this seems obvious, but I wanted to verify behavior.
Yes, the spec says that both examples should log 1 and then 2.