Skip to main content

return-await

Enforce consistent awaiting of returned promises.

🔒

ESLint 配置 中扩展"plugin:@typescript-eslint/strict-type-checked" 可启用此规则。

🔧

此规则报告的一些问题可通过 --fix ESLint 命令行选项自动修复

💡

此规则报告的一些问题可以通过编辑器 建议 手动修复。

💭

该规则需要 类型信息 才能运行,但这会带来性能方面的权衡。

async 函数中,返回承诺封装的值或直接返回值都是有效的,这两者最终都会产生具有相同履行值的承诺。返回值而不是承诺封装的值可以有几个微妙的好处:

¥In async functions, it is valid to return a promise-wrapped value or a value directly, both of which ultimately produce a promise with the same fulfillment value. Returning a value rather than a promise-wrapped value can have several subtle benefits:

此规则强制一致处理是否在返回承诺之前等待承诺。

¥This rule enforces consistent handling of whether to await promises before returning them.

信息

此规则曾被视为(现已弃用的)ESLint 核心规则 no-return-await 的扩展。如果没有类型信息,no-return-await 唯一可以标记的情况是中性到负值,这最终导致其弃用。相比之下,通过访问类型信息,@typescript-eslint/return-await 提供了足够的正值,使其在我们的严格预设中占有一席之地。

¥This rule used to be considered an extension of the (now-deprecated) ESLint core rule no-return-await. Without type information, the only situations that could be flagged by no-return-await were of neutral-to-negative value, which eventually led to its deprecation. In contrast, with access to type information, @typescript-eslint/return-await delivers enough positive value to earn it a spot in our strict preset.

如果你以前使用过 no-return-await,则此规则的 in-try-catch 选项的行为与 no-return-await 规则最接近。

¥If you previously used no-return-await, this rule's in-try-catch option has the closest behavior to the no-return-await rule.

eslint.config.mjs
export default tseslint.config({
rules: {
"@typescript-eslint/return-await": "error"
}
});

在线运行试试这个规则 ↗

选项

This rule accepts the following options, and has more strict settings in the strict and strict-type-checked configs.

type Options = [
/** Disallows awaiting any returned promises. */
| 'never'
/** In error-handling contexts, the rule enforces that returned promises must be awaited. In ordinary contexts, the rule does not enforce any particular behavior around whether returned promises are awaited. */
| 'error-handling-correctness-only'
/** In error-handling contexts, the rule enforces that returned promises must be awaited. In ordinary contexts, the rule enforces that returned promises _must not_ be awaited. */
| 'in-try-catch'
/** Requires that all returned promises be awaited. */
| 'always',
];

const defaultOptionsRecommended: Options = ['in-try-catch'];

// These options are merged on top of the recommended defaults
const defaultOptionsStrict: Options = ['error-handling-correctness-only'];

¥Options

type Options =
| 'in-try-catch'
| 'always'
| 'error-handling-correctness-only'
| 'never';

const defaultOptions: Options = 'in-try-catch';

此规则中的选项区分 "普通上下文" 和 "错误处理上下文"。错误处理上下文是返回未等待的承诺会导致与异常/拒绝有关的意外控制流的任何地方。有关每个选项的部分,请参阅详细示例。

¥The options in this rule distinguish between "ordinary contexts" and "error-handling contexts". An error-handling context is anywhere where returning an unawaited promise would cause unexpected control flow regarding exceptions/rejections. See detailed examples in the sections for each option.

  • 如果你在 try 块内返回一个承诺,则应该等待它以按预期触发后续的 catchfinally 块。

    ¥If you return a promise within a try block, it should be awaited in order to trigger subsequent catch or finally blocks as expected.

  • 如果你在 catch 块内返回一个承诺,并且有一个 finally 块,则应该等待它以按预期触发 finally 块。

    ¥If you return a promise within a catch block, and there is a finally block, it should be awaited in order to trigger the finally block as expected.

  • 如果你在 usingawait using 声明与其范围结束之间返回一个承诺,则应该等待它,因为它的行为相当于封装在 try 块中后跟 finally 的代码。

    ¥If you return a promise between a using or await using declaration and the end of its scope, it should be awaited, since it behaves equivalently to code wrapped in a try block followed by a finally.

普通上下文是可能返回承诺的任何其他位置。在普通上下文中是否等待返回的承诺的选择主要是风格上的。

¥Ordinary contexts are anywhere else a promise may be returned. The choice of whether to await a returned promise in an ordinary context is mostly stylistic.

在定义这些术语后,选项可以总结如下:

¥With these terms defined, the options may be summarized as follows:

选项普通上下文
(风格偏好🎨)
错误处理上下文
(捕获错误🐛)
我应该使用此选项吗?
alwaysreturn await promise;return await promise;✅ 是的!
in-try-catchreturn promise;return await promise;✅ 是的!
error-handling-correctness-only不关心 🤷return await promise;🟡 可以使用,但上述选项会更好。
neverreturn promise;return promise;
(⚠️ 这种行为可能有害⚠️)
❌ 不。此选项已弃用。

in-try-catch

在错误处理上下文中,规则强制要求必须等待返回的承诺。在普通情况下,规则强制要求不能等待返回的承诺。

¥In error-handling contexts, the rule enforces that returned promises must be awaited. In ordinary contexts, the rule enforces that returned promises must not be awaited.

如果你出于风格原因更喜欢较短的 return promise 形式,那么这是一个不错的选择,无论在哪里使用都是安全的。

¥This is a good option if you prefer the shorter return promise form for stylistic reasons, wherever it's safe to use.

带有 in-try-catch 的代码示例:

¥Examples of code with in-try-catch:

async function invalidInTryCatch1() {
try {
return Promise.reject('try');
} catch (e) {
// Doesn't execute due to missing await.
}
}

async function invalidInTryCatch2() {
try {
throw new Error('error');
} catch (e) {
// Unnecessary await; rejections here don't impact control flow.
return await Promise.reject('catch');
}
}

// Prints 'starting async work', 'cleanup', 'async work done'.
async function invalidInTryCatch3() {
async function doAsyncWork(): Promise<void> {
console.log('starting async work');
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('async work done');
}

try {
throw new Error('error');
} catch (e) {
// Missing await.
return doAsyncWork();
} finally {
console.log('cleanup');
}
}

async function invalidInTryCatch4() {
try {
throw new Error('error');
} catch (e) {
throw new Error('error2');
} finally {
// Unnecessary await; rejections here don't impact control flow.
return await Promise.reject('finally');
}
}

async function invalidInTryCatch5() {
return await Promise.resolve('try');
}

async function invalidInTryCatch6() {
return await 'value';
}

async function invalidInTryCatch7() {
using x = createDisposable();
return Promise.reject('using in scope');
}
Open in Playground

always

要求等待所有返回的承诺。

¥Requires that all returned promises be awaited.

如果你喜欢始终等待承诺的一致性,或者不想考虑错误处理上下文和普通上下文之间的区别,那么这是一个不错的选择。

¥This is a good option if you like the consistency of simply always awaiting promises, or prefer not having to consider the distinction between error-handling contexts and ordinary contexts.

带有 always 的代码示例:

¥Examples of code with always:

async function invalidAlways1() {
try {
return Promise.resolve('try');
} catch (e) {}
}

async function invalidAlways2() {
return Promise.resolve('try');
}

async function invalidAlways3() {
return await 'value';
}
Open in Playground

error-handling-correctness-only

在错误处理上下文中,规则强制要求必须等待返回的承诺。在普通情况下,规则不会强制任何特定的行为,即是否等待返回的承诺。

¥In error-handling contexts, the rule enforces that returned promises must be awaited. In ordinary contexts, the rule does not enforce any particular behavior around whether returned promises are awaited.

如果你只想从规则在错误处理上下文中捕获控制流错误的能力中受益,但不想强制执行特定的样式,那么这是一个不错的选择。

¥This is a good option if you only want to benefit from rule's ability to catch control flow bugs in error-handling contexts, but don't want to enforce a particular style otherwise.

信息

我们建议你配置 in-try-catchalways,而不是此选项。虽然在错误处理上下文之外等待承诺的选择主要是风格上的,但通常最好保持一致。

¥We recommend you configure either in-try-catch or always instead of this option. While the choice of whether to await promises outside of error-handling contexts is mostly stylistic, it's generally best to be consistent.

此规则使用 error-handling-correctness-only 的其他正确代码示例:

¥Examples of additional correct code with error-handling-correctness-only:

async function asyncFunction(): Promise<void> {
if (Math.random() < 0.5) {
return await Promise.resolve();
} else {
return Promise.resolve();
}
}
Open in Playground

never

不允许等待任何返回的承诺。

¥Disallows awaiting any returned promises.

警告

此选项已弃用,将在 typescript-eslint 的未来主要版本中删除。

¥This option is deprecated and will be removed in a future major version of typescript-eslint.

never 选项在错误处理上下文中引入了不良行为。如果你希望尽量减少返回等待的承诺,请考虑改用 in-try-catch,这通常也禁止返回等待的承诺,但仅限于不等待承诺是安全的情况下。

¥The never option introduces undesirable behavior in error-handling contexts. If you prefer to minimize returning awaited promises, consider instead using in-try-catch instead, which also generally bans returning awaited promises, but only where it is safe not to await a promise.

有关更多详细信息,请参阅 typescript-eslint#9433

¥See more details at typescript-eslint#9433.

带有 never 的代码示例:

¥Examples of code with never:

async function invalidNever1() {
try {
return await Promise.resolve('try');
} catch (e) {}
}

async function invalidNever2() {
return await Promise.resolve('try');
}

async function invalidNever3() {
return await 'value';
}
Open in Playground

何时不使用它

Type checked lint rules are more powerful than traditional lint rules, but also require configuring type checked linting.

See Troubleshooting > Linting with Type Information > Performance if you experience performance degradations after enabling type checked rules.

'## 资源'