-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Description
Search Terms
transpile async promise
Suggestion
When target is ES5, allow an option to transpile async/await to Promises rather than switches. This would require Promises to be polyfilled, hence would be optional.
Old issue for this
This was previously discussed on this issue but was closed with this comment by @mhegazy:
this may be true for code with small list of await expressions. but it does not scale for the general case. once you have a loop with an await expression, you can not use promises.
@mhegazy can you explain this? I have used fast-async to transpile loops to promises before. Is there some edge-case where it is not possible?
Use Cases
Current approach creates emitted code that cannot be source-mapped properly by some debuggers.
Examples
export const foo = async (): Promise<number> => await Promise.resolve(1) + 1;
Currently emits this:
exports.foo = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Promise.resolve(1)];
case 1: return [2 /*return*/, (_a.sent()) + 1];
}
}); }); };
Instead it should emit something like this (output from fast-async:
exports.foo = function foo() {
return new Promise(function ($return, $error) {
return Promise.resolve(1).then(function ($await_7) {
return $return($await_7 + 1);
}.$asyncbind(this, $error), $error);
});
};
Loops
Here's an example of fast-async transpiling a loop:
async function Foo() {
for (let x = 0; x < 5; x++) {
console.log("FOO: " + await Promise.resolve(x));
}
}
becomes
function Foo() {
return new Promise(function ($return, $error) {
var x;
x = 0;
function $Loop_4_step() {
x++;
return $Loop_4;
}
function $Loop_4() {
if (x < 5) {
return Promise.resolve(x).then(function ($await_6) {
console.log("FOO: " + $await_6);
return $Loop_4_step;
}.$asyncbind(this, $error), $error);
} else return [1];
}
return Function.$asyncbind.trampoline(this, $Loop_4_exit, $Loop_4_step, $error, true)($Loop_4);
function $Loop_4_exit() {
return $return();
}
});
}
Here's a while loop:
async function Foo() {
let x = 0;
while (x < 5) {
x += await Promise.resolve(1);
console.log("FOO: " + x);
}
}
transpiles to:
function Foo() {
return new Promise(function ($return, $error) {
var x;
x = 0;
function $Loop_4() {
if (x < 5) {
return Promise.resolve(1).then(function ($await_6) {
x += $await_6;
console.log("FOO: " + x);
return $Loop_4;
}.$asyncbind(this, $error), $error);
} else return [1];
}
return Function.$asyncbind.trampoline(this, $Loop_4_exit, $Loop_4, $error, true)($Loop_4);
function $Loop_4_exit() {
return $return();
}
});
}