Skip to content

codefix convertToAsync does not add await for returned values #27544

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

Closed
rradczewski opened this issue Oct 4, 2018 · 4 comments · Fixed by #27573
Closed

codefix convertToAsync does not add await for returned values #27544

rradczewski opened this issue Oct 4, 2018 · 4 comments · Fixed by #27573
Assignees

Comments

@rradczewski
Copy link

rradczewski commented Oct 4, 2018

First of all, thanks a lot for this refactoring, I think it's really useful and will push the adoption of async-await syntax 👍

This is a bug report related to this Twitter conversation: The converted code does not await for Promise.reject, thus the runtime does not throw but returns Promise.reject(3), which does not trigger the catch-clause but makes the function call return a rejected Promise.

I'm not 100% sure what the best conversion would be, but I assume it would be to always await for functions that could possibly return a Promise or expressions that are a Promise.

TypeScript Version: Tested against https://github.com/Microsoft/TypeScript/tree/v3.1.1 and 4ed85b7

Failing testcases:

These assume that the correct behavior is to add await to a returned expression that yields a Promise.

Search Terms:

  • async
  • convertToAsync

Code

function testcase() {
  return Promise.resolve(1)
    .then(x => Promise.reject(2))
    .catch(err => console.log(err));
}

Running testcase() code will log 2 and the returned Promise will resolve to undefined.

Expected behavior:

async function testcase() {
    try {
        const x = await Promise.resolve(1);
        return await Promise.reject(2);
    }
    catch (err) {
        return console.log(err);
    }
}

A call to testcase() would print 2 and the returned Promise would resolve to undefined as above.

Actual behavior:

async function testcase() {
    try {
        const x = await Promise.resolve(1);
        return Promise.reject(2);
    }
    catch (err) {
        return console.log(err);
    }
}

A call to testcase() this won't print 2 but node will complain about an unhandled rejected promise.

Related Issues:

@j-oliveras
Copy link
Contributor

The await is not necessary:

An async function always wraps the return value in a Promise. Using return await just adds extra time before the overreaching promise is resolved without changing the semantics.

From no-return-await tslint rule.

@j-oliveras
Copy link
Contributor

Tested with node 8.11.1 and it seems is necessary to await Promise.reject rejections but not resolve at return position.

@j-oliveras
Copy link
Contributor

I found and explanation when is necessary an await: https://stackoverflow.com/a/42750371

With the await, it is catched by the catch block. Without it, returns the promise and then is resolved (or rejected in this case).

@uniqueiniquity maybe, convertToAsync should await the return if it inside a catch block.

@uniqueiniquity uniqueiniquity self-assigned this Oct 4, 2018
@uniqueiniquity
Copy link
Contributor

@rradczewski thanks for reporting, and @j-oliveras thanks for the investigation! I'll tackle this as soon as I can.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants