Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transpiling async/await to promises instead of generators for es5 #31621

Open
collinsauve opened this issue May 28, 2019 · 2 comments
Open

Transpiling async/await to promises instead of generators for es5 #31621

collinsauve opened this issue May 28, 2019 · 2 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@collinsauve
Copy link

collinsauve commented May 28, 2019

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();
    }
  });
}
@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript labels Jun 13, 2019
@JounQin
Copy link

JounQin commented Sep 18, 2019

+1 for this, would it be possible to integrate with fast-async?

@ivan-zakharchuk
Copy link

ivan-zakharchuk commented May 18, 2020

that's true, the current implementation is virtually impossible to understand/debug in production code that is shipped without source maps but with Promises simply pretty print of any debugger is enough.
Still, lots of enterprise products support IE11 and it makes usage of async/await impossible for such projects until the whole team learns how _awaiter works and code transpiled to Promises would be great if possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants