eslint: Rule Change: return await is both faster and allows better error handling
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
async function do(url) {
return await fetch(url);
}
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
- I am willing to submit a pull request to implement this change.
Additional comments
The docs state:
You can avoid the extra microtask by not awaiting the return value, with the trade off of the function no longer being a part of the stack trace if an error is thrown asynchronously from the Promise being returned. This can make debugging more difficult.
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:
async function test(name, fn) {
let tick = 0;
const tock = () => tick++;
Promise.resolve().then(tock).then(tock).then(tock);
const p = await fn();
console.assert(p === 42);
console.log(name, tick);
}
await Promise.all([
test('nonpromise-sync', () => 42),
test('nonpromise-async', async () => 42),
test('nonpromise-async-await', async () => await 42),
test('promise-sync', () => Promise.resolve(42)),
test('promise-async', async () => Promise.resolve(42)),
test('promise-async-await', async () => await Promise.resolve(42)),
]);
setTimeout(() => {}, 100);
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.
function errorThrower () {
return Promise.reject('fail');
}
function returnNoAwait() {
try {
return errorThrower();
} catch {
console.log('I want to catch, but I am never executed');
}
}
async function returnAwait() {
try {
return await errorThrower();
} catch(e) {
console.log('I caught an error. I still have e, so I can rethrow.');
}
}
await returnAwait();
await returnNoAwait();
Yields:
I caught an error. I still have e, so I can rethrow.
Uncaught fail
And note that uncaught fail will crash some environments.
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 15 (15 by maintainers)
Commits related to this issue
- fix(no-return-await): only warn about literals and undefined In async functions, returning awaited promises no longer has any performance penalty and is now faster than returning promises directly. ... — committed to clshortfuse/eslint by clshortfuse a year ago
- fix: only warn about literals and undefined on no-return-await In async functions, returning awaited promises no longer has any performance penalty and is now faster than returning promises directly.... — committed to clshortfuse/eslint by clshortfuse a year ago
- 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 th... — committed to clshortfuse/eslint by clshortfuse a year ago
- feat: deprecate no-return-await (#17417) * fix: deprecate no-return-await The original intent of this rule no longer applies due to the fact Javascript now handles native `Promises` differently. I... — committed to eslint/eslint by clshortfuse a year ago
- Update eslint to v8.46.0 * Enable `no-irregular-whitespace` for strings. * Disable `no-return-await` as deprecated (see https://github.com/eslint/eslint/issues/17345 for rationale). — committed to perfective/eslint-config by amikheychik a year ago
@clshortfuse here’s an example: https://github.com/eslint/eslint/commit/5ed8b9bd6799116af2790225a23a324a8a8ef336
It seems like there’s agreement to update the documentation for this rule. @clshortfuse do you want to submit a PR for that?
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.
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 https://github.com/tc39/ecma262/pull/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.