return await
強制一致等待傳回 promise。
此規則奠基於 eslint/no-return-await
規則。其擴充基本規則,針對特定情況新增支援,強制使用 return await
。
已擴充的規則稱為 return-await
,而非 no-return-await
,因為已擴充的規則可強制執行正向或負向。此外,雖然核心規則現已不建議使用,但已擴充的規則在許多情況下仍很有用
- 傳回一個已等待的 promise 可 改善堆疊追蹤資訊。
- 當
return
陳述式在try...catch
中,等待 promise 同時也能攔截 promise 的 rejection,而不是讓錯誤交由呼叫者處理。 - 與普遍認為相反,
return await promise;
至少與直接傳回 promise 一樣快。
如何使用
.eslintrc.cjs
module.exports = {
"rules": {
// Note: you must disable the base rule as it can report incorrect errors
"no-return-await": "off",
"@typescript-eslint/return-await": "error"
}
};
在遊樂場測試這個規則 ↗
選項
請參閱 eslint/no-return-await
選項。
type Options = 'in-try-catch' | 'always' | 'never';
const defaultOptions: Options = 'in-try-catch';
in-try-catch
在 `return` 尚未等待的 promise 會造成錯誤處理控制流程時,規則強制執行必須使用 `await`。否則,此規則強制執行不得使用 `await`。
詳盡列出錯誤處理案例
- 如果在 `try` 內 `return` 一個 promise,則必須使用 `await`,因為它後面接的永遠會是 `catch` 或 `finally`。
- 如果在 `catch` 內 `return` 一個 promise,而沒有 `finally`,則不得使用 `await`。
- 如果在 `catch` 內 `return` 一個 promise,而且有 `finally`,則必須使用 `await`。
- 如果在 `finally` 內 `return` 一個 promise,則不得使用 `await`。
- 如果在 `using` 或 `await using` 宣告與其範圍的尾端之間 `return` 一個 promise,則必須使用 `await`,因為其行為等同於包裹在 `try` 區塊內的程式碼。
- ❌ 不正確
- ✅ 正確
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');
}
在遊樂場中開啟async function validInTryCatch1() {
try {
return await Promise.reject('try');
} catch (e) {
// Executes as expected.
}
}
async function validInTryCatch2() {
try {
throw new Error('error');
} catch (e) {
return Promise.reject('catch');
}
}
// Prints 'starting async work', 'async work done', 'cleanup'.
async function validInTryCatch3() {
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) {
return await doAsyncWork();
} finally {
console.log('cleanup');
}
}
async function validInTryCatch4() {
try {
throw new Error('error');
} catch (e) {
throw new Error('error2');
} finally {
return Promise.reject('finally');
}
}
async function validInTryCatch5() {
return Promise.resolve('try');
}
async function validInTryCatch6() {
return 'value';
}
async function validInTryCatch7() {
using x = createDisposable();
return await Promise.reject('using in scope');
}
在遊樂場中開啟always
表示所有已傳回的 promise 都必須使用 `await`。
使用 `always` 的程式碼範例
- ❌ 不正確
- ✅ 正確
async function invalidAlways1() {
try {
return Promise.resolve('try');
} catch (e) {}
}
async function invalidAlways2() {
return Promise.resolve('try');
}
async function invalidAlways3() {
return await 'value';
}
在遊樂場中開啟async function validAlways1() {
try {
return await Promise.resolve('try');
} catch (e) {}
}
async function validAlways2() {
return await Promise.resolve('try');
}
async function validAlways3() {
return 'value';
}
在遊樂場中開啟never
不允許等待任何已傳回的 promise。
使用 `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';
}
在遊樂場中開啟async function validNever1() {
try {
return Promise.resolve('try');
} catch (e) {}
}
async function validNever2() {
return Promise.resolve('try');
}
async function validNever3() {
return 'value';
}
在遊樂場中開啟何時不使用
已類型檢查的 lint 規則比傳統的 lint 規則更有力,但同時也需要設定已類型檢查的 linting。如果在啟用已類型檢查的規則後發現效能變差,請參閱效能問題修復。