新聞中心
異步代碼的ESLint規(guī)則
以下規(guī)則默認(rèn)隨ESLint一起提供,可以在 .eslintrc 配置文件中啟用它們。

1. no-async-promise-executor
此規(guī)則不允許將 async 函數(shù)傳遞給 new Promise 構(gòu)造函數(shù)。
//
new Promise(async (resolve, reject) => {});
//
new Promise((resolve, reject) => {});
雖然將異步函數(shù)傳遞給 Promise 構(gòu)造函數(shù)在技術(shù)上是沒(méi)有問(wèn)題的,但由于以下兩個(gè)原因,這樣做通常都是錯(cuò)誤的:
- 如果異步函數(shù)拋出錯(cuò)誤,錯(cuò)誤將會(huì)丟失而不會(huì)被新構(gòu)造的 Promise 拒絕;
- 如果 await 在構(gòu)造函數(shù)內(nèi)部使用,包裝 Promise 是不必要的,可以將其刪除。
2. no-await-in-loop
此規(guī)則不允許在循環(huán)內(nèi)使用 await。
當(dāng)對(duì)可迭代的每個(gè)元素執(zhí)行操作并等待異步任務(wù)時(shí),通常表明程序沒(méi)有充分利用 JavaScript 的事件驅(qū)動(dòng)架構(gòu)。通過(guò)并行執(zhí)行這些任務(wù),可以大大提高代碼的效率。
//
for (const url of urls) {
const response = await fetch(url);
}
//
const responses = [];
for (const url of urls) {
const response = fetch(url);
responses.push(response);
}
await Promise.all(responses);
當(dāng)確實(shí)需要按照順序執(zhí)行任務(wù)的情況下,建議使用內(nèi)聯(lián)注釋禁用此規(guī)則:
// eslint-disable-line no-await-in-loop。
3. no-promise-executor-return
此規(guī)則不允許在 Promise 構(gòu)造函數(shù)中返回值。
//
new Promise((resolve, reject) => {
return result;
});
//
new Promise((resolve, reject) => {
resolve(result);
});
在 Promise 構(gòu)造函數(shù)中返回的值不能被使用并且不會(huì)以任何方式影響 Promise。應(yīng)該將值傳遞給 resolve,如果發(fā)生錯(cuò)誤,則調(diào)用 reject 并顯示錯(cuò)誤。
此規(guī)則不會(huì)阻止在 Promise 構(gòu)造函數(shù)的嵌套回調(diào)中返回值。始終確保使用 resolve 或 reject 來(lái)完成 Promise。
4. require-atomic-updates
此規(guī)則不允許由于 await 或 yield 的使用而可能導(dǎo)致出現(xiàn)競(jìng)態(tài)條件的賦值。
來(lái)看下面的例子,totalPosts 的最終值是多少?
//
let totalPosts = 0;
async function getPosts(userId) {
const users = [{ id: 1, posts: 5 }, { id: 2, posts: 3 }];
await sleep(Math.random() * 1000);
return users.find((user) => user.id === userId).posts;
}
async function addPosts(userId) {
totalPosts += await getPosts(userId);
}
await Promise.all([addPosts(1), addPosts(2)]);
console.log('Post count:', totalPosts);
這里 totalPosts 不會(huì)打印 8,而會(huì)打印 5 和 3。問(wèn)題就在于讀取和更新 totalPosts 之間存在時(shí)間間隔。這會(huì)導(dǎo)致競(jìng)態(tài)條件,使得在單獨(dú)的函數(shù)調(diào)用中更新值時(shí),更新不會(huì)反映在當(dāng)前函數(shù)范圍中。因此,這兩個(gè)函數(shù)都將它們的結(jié)果添加到初始值為 0 的 totalPosts 中。
為了避免這種競(jìng)態(tài)條件,應(yīng)該確保在更新變量的同時(shí)讀取變量:
//
let totalPosts = 0;
async function getPosts(userId) {
const users = [{ id: 1, posts: 5 }, { id: 2, posts: 3 }];
await sleep(Math.random() * 1000);
return users.find((user) => user.id === userId).posts;
}
async function addPosts(userId) {
const posts = await getPosts(userId);
totalPosts += posts; // variable is read and immediately updated
}
await Promise.all([addPosts(1), addPosts(2)]);
console.log('Post count:', totalPosts);
5. max-nested-callbacks
此規(guī)則會(huì)強(qiáng)制回調(diào)的最大嵌套深度。換句話說(shuō),這條規(guī)則可以防止回調(diào)地獄。
/* eslint max-nested-callbacks: ["error", 3] */
//
async1((err, result1) => {
async2(result1, (err, result2) => {
async3(result2, (err, result3) => {
async4(result3, (err, result4) => {
console.log(result4);
});
});
});
});
//
const result1 = await asyncPromise1();
const result2 = await asyncPromise2(result1);
const result3 = await asyncPromise3(result2);
const result4 = await asyncPromise4(result3);
console.log(result4);
深層的嵌套使代碼難以閱讀和維護(hù)。在編寫 JavaScript 異步代碼時(shí),可以將回調(diào)重構(gòu)為 Promise 并使用 async/await 語(yǔ)法。
6. no-return-await
此規(guī)則不允許返回不必要的 await。
//
async () => {
return await getUser(userId);
}
//
async () => {
return getUser(userId);
}
等待一個(gè) Promise 并立即返回它是沒(méi)有必要的,因?yàn)閺漠惒胶瘮?shù)返回的所有值都包含在一個(gè) Promise 中。因此,可以直接返回 Promise。
此規(guī)則的一個(gè)例外情況就是當(dāng)有 try...catch 語(yǔ)句時(shí), 刪除 await 關(guān)鍵字將導(dǎo)致不會(huì)捕獲 Promise 拒絕的原因。在這種情況下,建議將結(jié)果分配給變量以明確意圖。
//
async () => {
try {
return await getUser(userId);
} catch (error) {
// 處理錯(cuò)誤
}
}
//
async () => {
try {
const user = await getUser(userId);
return user;
} catch (error) {
// 處理錯(cuò)誤
}
}
7. prefer-promise-reject-errors
此規(guī)則在拒絕 Promise 時(shí)強(qiáng)制使用 Error 對(duì)象。
//
Promise.reject('An error occurred');
//
Promise.reject(new Error('An error occurred'));
最好的做法就是始終拒絕帶有 Error 對(duì)象的 Promise。這樣做將更容易跟蹤錯(cuò)誤的來(lái)源,因?yàn)?Error 對(duì)象存儲(chǔ)在堆棧跟蹤中。
Node.js 特定規(guī)則
以下規(guī)則是 eslint-plugin-node 插件為 Node.js 提供的附加 ESLint 規(guī)則。要使用它們,需要安裝插件并將其添加到 .eslintrc 配置文件中的 plugins 數(shù)組中。
8. node/handle-callback-err
此規(guī)則在回調(diào)中強(qiáng)制執(zhí)行錯(cuò)誤處理。
//
function callback(err, data) {
console.log(data);
}
//
function callback(err, data) {
if (err) {
console.log(err);
return;
}
console.log(data);
}
在 Node.js 中,通常將錯(cuò)誤作為第一個(gè)參數(shù)傳遞給回調(diào)函數(shù)。忘記處理錯(cuò)誤可能會(huì)導(dǎo)致應(yīng)用程序行為異常。
當(dāng)函數(shù)的第一個(gè)參數(shù)命名為 err 時(shí)會(huì)觸發(fā)此規(guī)則??梢酝ㄟ^(guò)在 .eslintrc 文件中為規(guī)則提供第二個(gè)參數(shù)來(lái)更改默認(rèn)配置:
node/handle-callback-err: ["error", "^(e|err|error)$"]
9. node/no-callback-literal
此規(guī)則強(qiáng)制使用 Error 對(duì)象作為第一個(gè)參數(shù)調(diào)用回調(diào)函數(shù)。如果沒(méi)有 Error,會(huì)接受 null 或 undefined 。
//
cb('An error!');
callback(result);
//
cb(new Error('An error!'));
callback(null, result);
此規(guī)則可以確保不會(huì)意外調(diào)用以非 error 作為第一個(gè)參數(shù)的回調(diào)函數(shù)。根據(jù) error 優(yōu)先回調(diào)約定,回調(diào)函數(shù)的第一個(gè)參數(shù)應(yīng)該是 error,如果沒(méi)有 Error,則為 null 或 undefined。
注意:僅當(dāng)函數(shù)命名為 cb 或 callback 時(shí)才會(huì)觸發(fā)此規(guī)則。
10. node/no-sync
此規(guī)則不允許在存在異步替代方案的 Node.js 核心 API 中使用同步方法。
//
const file = fs.readFileSync(path);
//
const file = await fs.readFile(path);
在 Node.js 中對(duì) I/O 操作使用同步方法會(huì)阻塞事件循環(huán)。在大多數(shù) Web 應(yīng)用程序中,執(zhí)行 I/O 操作時(shí)會(huì)使用異步方法。
在某些應(yīng)用程序中,可以使用同步方法。可以在代碼文件頂部使用以下代碼來(lái)禁用此規(guī)則:
/* eslint-disable node/no-sync */
TypeScript 特定規(guī)則以下規(guī)則僅適用于 TypeScript 項(xiàng)目。
11. @typescript-eslint/await-thenable
此規(guī)則不允許 await 不是 Promise 的函數(shù)或值。
//
function getValue() {
return someValue;
}
await getValue();
//
async function getValue() {
return someValue;
}
await getValue();
雖然在 JavaScript 中 await 非 Promise 值是有效的(將立即解析),但它通常表示代碼邏輯是錯(cuò)誤的,例如忘記添加括號(hào)來(lái)調(diào)用返回 Promise 的函數(shù)。
12. @typescript-eslint/no-floating-promises
此規(guī)則強(qiáng)制 Promises 添加錯(cuò)誤處理程序。
myPromise()
.then(() => {});
//
myPromise()
.then(() => {})
.catch(() => {});
此規(guī)則可防止代碼庫(kù)中的浮動(dòng) Promise。浮動(dòng) Promise 是沒(méi)有任何代碼來(lái)處理潛在錯(cuò)誤的 Promise。
13. @typescript-eslint/no-misused-promises
此規(guī)則不允許將 Promise 傳遞到并非旨在處理它們的地方,例如 if 條件:
//
if (getUserFromDB()) {}
//
if (await getUserFromDB()) {}
//
const user = await getUserFromDB();
if (user) {}
此規(guī)則可防止忘記添加 await 異步函數(shù)。雖然該規(guī)則確實(shí)允許在 if 條件中 await,但建議將結(jié)果分配給一個(gè)變量并在條件中使用該變量以提高可讀性。
14. @typescript-eslint/promise-function-async
此規(guī)則強(qiáng)制返回 Promise 的是 async 函數(shù)。
//
function doSomething() {
return somePromise;
}
//
async function doSomething() {
return somePromise;
}
返回 Promise 的非異步函數(shù)可能會(huì)拋出 Error 對(duì)象并返回被拒絕的 Promise。通常不會(huì)編寫代碼來(lái)處理這兩種情況。此規(guī)則確保函數(shù)返回被拒絕的 Promise 或拋出 Error,但絕不會(huì)兩者都有。
網(wǎng)站題目:14條ESLint規(guī)則讓你的異步代碼更優(yōu)雅
網(wǎng)頁(yè)地址:http://www.dlmjj.cn/article/dhgijjg.html


咨詢
建站咨詢
