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
Rule Change: return await is both faster and allows better error handling #17345
Comments
Hi @clshortfuse, thanks for the issue! There have been a lot of discussions about this rule.
I think this was true at the time when the rule was created but may have become false after tc39/ecma262#1250.
We can't change the no-return-await rule to suggest return await. I think the best past forward for this rule is to update the docs saying that the rationale for the rule is to warn about redundant code. |
Sounds reasonable. I think such an update would make the rule classify as stylistic? |
In addition to the new spec changes (I do mention that in the stackoverflow), it is technically faster if you're not using promises eg: The real micro-optimization logic is:
You would need something like |
I think yes, since it reports logical redundancy that no longer negatively impacts performance according to the current state of the ES spec and implementations. |
It seems like there's agreement to update the documentation for this rule. @clshortfuse do you want to submit a PR for that? |
In async functions, returning awaited promises no longer has any performance penalty and is now faster than returning promises directly. Because we cannot detect what the result type of a `CallExpression` or the type of a `MemberExpression`, or the type of an `Identifier`, warnings related to whether an actual Promise is being returned cannot be processed. Strictly from at an AST level, we can detect `Literal` node types and `undefined`. * Detect await being used on `Literal` node type * Detect await being used on an `Identifier` named `undefined` * Detect await being used on a `ConditionalExpression` that returns either a `Literal` type or `undefined`. * Detect await being used on a void operation (results in `undefined`) Futher changes can be made to detect syntaxes where a `Literal` type would be returned, such as * await (4 + 3) * await ('foo' + 'bar') Future changes may also, suggest rewriting awaited `CondtionExpression` nodes such as: * async function foo(value) { return await (value ? true : bar()) } This would require more extensive testing. Fixes eslint#17345 See: https://v8.dev/blog/fast-async
In async functions, returning awaited promises no longer has any performance penalty and is now faster than returning promises directly. Because we cannot detect what the result type of a `CallExpression` or the type of a `MemberExpression`, or the type of an `Identifier`, warnings related to whether an actual Promise is being returned cannot be processed. Strictly from at an AST level, we can detect `Literal` node types and `undefined`. * Detect await being used on `Literal` node type * Detect await being used on an `Identifier` named `undefined` * Detect await being used on a `ConditionalExpression` that returns either a `Literal` type or `undefined`. * Detect await being used on a void operation (results in `undefined`) Futher changes can be made to detect syntaxes where a `Literal` type would be returned, such as * await (4 + 3) * await ('foo' + 'bar') Future changes may also, suggest rewriting awaited `CondtionExpression` nodes such as: * async function foo(value) { return await (value ? true : bar()) } This would require more extensive testing. See: https://v8.dev/blog/fast-async Fixes eslint#17345
Apologies. It seems I misunderstood the intent here. I understood that the rule is now merely of stylistic use to users and no longer something worth recommending. Bluntly stated, the rule should be removed or changed to better align to ECMAScript spec. There are no documentation-only "fixes" I see that can be made. I have a PR that target using return await on literals and undefined because there is no other reason I see for keeping the rule. |
@clshortfuse I think the idea was to replace misleading information in the rule docs (e.g. "avoid the extra microtask", "a likely common performance hazard", etc.), without changing the logic. I'm on your side in arguing that this was not very clear from the previous discussion. |
The problem is the entire point of the rule is as follows:
The raison d'etre (core reason) for the rule is now invalid. I originally stated that we actually want to encourage return await, though that kinda doesn't make sense for a rule called no-return-await to suggest return await. That's how I interpreted the previous comments. I'm not sure what documentation-only may exist. If the original motivation of the rule is promote better performance, then the rule should actually promote better performance, and that means it is essentially a rule change/modification. There is a small carve-out where we can still keep promoting this rule, and it's as I scripted in the PR. Currently, as it stands, the rule, when applies with the suggestions, does the opposite of it's intended purpose. Applying the eslint rule degrades performance. Sorry if I sound like I'm repeating myself, but essentially I don't see how we can not modify the rule given the "new" spec that's been in place for about 5 years. |
The original motivation for the rule was to report logically redundant code and improve performance. I think the first point is still valid stylistically, and my suggestion was to update the documentation with the new facts about performance.
I'd be also fine with deprecating this rule. |
I'm fine with deprecating the rule, but we'd still need the documentation updated with that. |
Note that we have |
Here's what I'm thinking: Because
I personally use the At the same time, I lean on deprecation because the nature of await has changed, but I would wonder if @bradzacher is interested in allowing a bit more options for the typescript version. |
@clshortfuse we've already mentioned above that we'd like to deprecate the rule and update the documentation. :) |
@nzakas Yeah, that's fine, as I said. But:
|
@clshortfuse here's an example: 5ed8b9b |
The original intent of this rule no longer applies due to the fact Javascript now handles native `Promises` differently. It can no be slower to remove `await` rather than keeping it. Fixes eslint#17345
* fix: deprecate no-return-await The original intent of this rule no longer applies due to the fact Javascript now handles native `Promises` differently. It can no be slower to remove `await` rather than keeping it. Fixes #17345 * Update docs/src/rules/no-return-await.md Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com> * Update lib/rules/no-return-await.js Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com> * Update docs/src/rules/no-return-await.md --------- Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com> Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com>
* Enable `no-irregular-whitespace` for strings. * Disable `no-return-await` as deprecated (see eslint/eslint#17345 for rationale).
What rule do you want to change?
no-return-await
What change to do you want to make?
Generate fewer warnings
How do you think the change should be implemented?
A new default behavior
Example code
What does the rule currently do for this code?
Eslint will say to remove
await
with the docs saying:What will the rule do after it's changed?
Suggest
return await
. (Or at least not misinform authors).Participation
Additional comments
The docs state:
This is actually false and if that is the reasoning then it should be changed. I have a long explanation of the mechanics as to why
return await
is faster at this Stackoverflow comment but to keep this brief, you can run this:And you'll see that returning a Promise (not using return await) is the slowest method.
There is also an added benefit (maybe) that execution (resolving) happens within the function itself, so you can catch errors. If you try to add a catch to a returning Promise, it'll never fire.
Yields:
And note that uncaught fail will crash some environments.
The text was updated successfully, but these errors were encountered: