日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

帮助编写异步代码的ESLint规则

發布時間:2024/1/21 windows 40 coder
生活随笔 收集整理的這篇文章主要介紹了 帮助编写异步代码的ESLint规则 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

調試 JavaScript 中的異步代碼有時就像在雷區中穿梭。你不知道 console.log 會在何時何地打印出來,也不知道代碼是如何執行的。

你很難正確構造異步代碼,使其按照你的意圖以正確的順序執行。

如果在編寫異步代碼時能得到一些指導,并在即將出錯時收到一條有用的信息,那豈不更好?

幸運的是,在將錯誤推向生產環境之前,我們有一些規則來捕捉這些錯誤。以下是一份經過編譯的linting規則列表,可為你在 JavaScript 和 Node.js 中編寫異步代碼提供具體幫助。

即使你最終沒有在項目中使用這些規則,閱讀它們的說明也會讓你更好地理解異步代碼,并提高你的開發技能。

ESLint異步代碼規則

ESLint 默認提供以下規則。將它們添加到 .eslintrc 配置文件中即可啟用。

no-async-promise-executor

該規則不允許將async函數傳遞給new Promise構造函數。

// ?
new Promise(async (resolve, reject) => {});

// ?
new Promise((resolve, reject) => {});

雖然從技術上講,向 Promise 構造函數傳遞異步函數是有效的,但出于以下兩個原因,這樣做通常是錯誤的。首先,如果異步函數拋出錯誤,錯誤將丟失,不會被新構造的 Promise 拒絕。其次,如果在構造函數內部使用了 await,那么外層的 Promise 可能就沒有必要了,可以將其刪除。

no-await-in-loop

該規則不允許在循環內使用await。

在對可迭代對象的每個元素進行操作并等待異步任務時,往往表明程序沒有充分利用 JavaScript 的事件驅動架構。通過并行執行任務,可以大大提高代碼的效率。

// ?
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);

如果你想按順序運行任務,我建議你使用行內注釋暫時禁用該規則:// eslint-disable-line no-await-in-loop。

no-promise-executor-return

該規則不允許在 Promise 構造函數中返回值。

// ?
new Promise((resolve, reject) => {
  return result;
});

// ?
new Promise((resolve, reject) => {
  resolve(result);
});

在 Promise 構造函數中返回的值不能使用,也不會對 promise 產生任何影響。應將該值傳遞給resolve,如果發生錯誤,則調用 reject 并告知錯誤信息。

該規則不會阻止你在 Promise 構造函數中的嵌套回調內返回值。請務必使用 resolvereject 來結束promise。

require-atomic-updates

該規則不允許將賦值與 await 結合使用,否則會導致競賽條件。

請看下面的示例,你認為 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);

也許你已經感覺到這是一個騙人的問題,答案不是 8。沒錯,totalPosts 打印的是 5 或 3。自己在瀏覽器中試試吧。

問題在于讀取和更新 totalPosts 之間存在時間差。這就造成了一個競賽條件,當值在單獨的函數調用中更新時,更新不會反映在當前函數的作用域中。因此,這兩個函數都將其結果添加到 totalPosts 的初始值 0 中。

要避免這種競賽條件,應確保在更新變量的同時讀取變量。

// ?
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);

max-nested-callbacks

該規則強制限制回調的最大嵌套深度。換句話說,該規則可防止回調地獄!

/* 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);

深度嵌套會使代碼難以閱讀,更難以維護。在編寫 JavaScript 異步代碼時,將回調重構為promise,并使用現代的 async/await 語法。

no-return-await

該規則不允許不必要的return await。

// ?
async () => {
  return await getUser(userId);
}

// ?
async () => {
  return getUser(userId);
}

由于async函數返回的所有值都已封裝在 promise 中,因此等待 promise 并立即返回是不必要的。因此,你可以直接返回 promise。

當周圍有 try...catch 語句時,這條規則會出現例外。移除 await 關鍵字會導致不捕獲拒絕的promise。在這種情況下,我建議你將結果賦值給另一行的變量,以明確意圖。

// ??
async () => {
  try {
    return await getUser(userId);
  } catch (error) {
    // Handle getUser error
  }
}

// ??
async () => {
  try {
    const user = await getUser(userId);
    return user;
  } catch (error) {
    // Handle getUser error
  }
}

prefer-promise-reject-errors

該規則強制要求在拒絕 Promise 時使用 Error 對象。

// ?
Promise.reject('An error occurred');

// ?
Promise.reject(new Error('An error occurred'));

最佳做法是始終使用 Error 對象來拒絕Promise。因為錯誤對象會存儲堆棧跟蹤,所以這樣做可以更容易地跟蹤錯誤的來源。

Node.js 特定規則

以下規則是 esLint-plugin-node 插件為 Node.js 提供的附加 ESLint 規則。要使用這些規則,需要安裝該插件并將其添加到 .eslintrc 配置文件的 plugins 數組中。

node/handle-callback-err

該規則強制在回調中處理錯誤。

// ?
function callback(err, data) {
  console.log(data);
}

// ?
function callback(err, data) {
  if (err) {
    console.log(err);
    return;
  }

  console.log(data);
}

在 Node.js 中,將錯誤作為第一個參數傳遞給回調函數是很常見的。忘記處理錯誤會導致應用程序行為異常。

當函數的第一個參數名為 err 時,就會觸發該規則。在大型項目中,經常會發現不同的錯誤命名方式,如 eerror。你可以通過在 .eslintrc 文件中為規則提供第二個參數來更改默認配置:node/handle-callback-err: ["error", "^(e|err|error)$"]

node/no-callback-literal

該規則強制要求在調用回調函數時將 Error 對象作為第一個參數。如果沒有錯誤,也接受 nullundefined。

// ?
cb('An error!');
callback(result);

// ?
cb(new Error('An error!'));
callback(null, result);

該規則可確保你不會意外調用第一個參數為非錯誤的回調函數。根據錯誤優先的回調約定,回調函數的第一個參數應該是錯誤,如果沒有錯誤,則應該是 nullundefined

只有當函數名為 cbcallback 時,才會觸發該規則。

node/no-sync

如果 Node.js 核心 API 中存在異步替代方法,則該規則不允許使用同步方法。

// ?
const file = fs.readFileSync(path);

// ?
const file = await fs.readFile(path);

在 Node.js 中使用同步方法進行 I/O 操作會阻止事件循環。在大多數網絡應用程序中,進行 I/O 操作時需要使用異步方法。

在 CLI 實用程序或腳本等某些應用程序中,使用同步方法也是可以的。你可以使用 /* eslint-disable node/no-sync */ 在文件頂部禁用這一規則。

針對 TypeScript 用戶的附加規則

如果你的項目使用的是 TypeScript,那么你可能已經熟悉了 TypeScript ESLint(以前的 TSLint)。以下規則僅適用于 TypeScript 項目,因為它們會從類型信息中推斷出額外的上下文。

@typescript-eslint/await-thenable

該規則不允許等待非 Promise 的函數或值。

// ?
function getValue() {
  return someValue;
}

await getValue();

// ?
async function getValue() {
  return someValue;
}

await getValue();

雖然等待一個非 Promise 的值是有效的 JavaScript(它會立即解析),但這往往表明程序員出錯了,比如在調用一個返回 Promise 的函數時忘記加上括號。

@typescript-eslint/no-floating-promises

此規則強制 Promise 必須附加錯誤處理程序。

// ?
myPromise()
  .then(() => {});

// ?
myPromise()
  .then(() => {})
  .catch(() => {});

此規則可防止代碼庫中出現浮動 Promise。浮動 Promise 是指沒有任何代碼來處理潛在錯誤的 Promise。

請務必處理 Promise 拒絕,否則你的 Node.js 服務器將會崩潰。

@typescript-eslint/no-misused-promises

該規則禁止將 Promise 傳遞到非處理 Promise 的地方,如 if 條件語句。

// ?
if (getUserFromDB()) {}

// ? ??
if (await getUserFromDB()) {}

// ? ??
const user = await getUserFromDB();
if (user) {}

該規則可防止你在容易遺漏的地方忘記 await 異步函數。

雖然該規則允許在 if 條件語句中等待,但我建議將結果賦值給一個變量,然后在條件中使用該變量,以提高可讀性。

@typescript-eslint/promise-function-async

該規則強制 Promise 返回函數必須是 async 。

// ?
function doSomething() {
  return somePromise;
}

// ?
async function doSomething() {
  return somePromise;
}

返回promise的非同步函數可能會有問題,因為它可能會拋出一個 Error 對象并返回一個被拒絕的promise。代碼通常不會同時處理這兩種情況。本規則可確保函數返回被拒絕的promise或拋出 Error,但絕不會同時返回兩種情況。

此外,如果知道所有返回 Promise 的函數都被標記為 async ,那么瀏覽代碼庫就容易多了。

啟用這些規則

我發布了一個 ESLint 配置包,你可以輕松將其添加到你的項目中。它分別導出了基本規則、Node.js 特定規則和 TypeScript 特定規則。

針對非TypeScript用戶

npm install --save-dev eslint eslint-config-async eslint-plugin-node

然后在你的 .eslintrc 配置文件中添加下列配置:

{
  "plugins": [
    "eslint-plugin-node"
  ],
  "extends": [
    "async",
    "async/node"
  ]
}

針對TypeScript用戶

安裝包及其依賴:

npm install --save-dev eslint eslint-config-async eslint-plugin-node typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin

然后在你的 .eslintrc 配置文件中添加下列配置:

"plugins": [
  "eslint-plugin-node",
  "@typescript-eslint"
],
"extends": [
  "async",
  "async/node",
  "async/typescript"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
  "tsconfigRootDir": "__dirname",
  "project": ["./tsconfig.json"],
};

就是這樣!將這些異步代碼的校驗規則添加到你的項目中,并修復出現的任何問題。你可能會發現一兩個 bug!?? ??

以上就是本文的全部內容,如果對你有所幫助,歡迎點贊、收藏、轉發~

總結

以上是生活随笔為你收集整理的帮助编写异步代码的ESLint规则的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。