簡體   English   中英

在 Async/Await 下留下無用的同步代碼是一種反模式嗎?

[英]Is leaving useless synchronous code under Async/Await an anti-pattern?

據我了解, await背后的要點是“等待”對 promise 的解析值執行操作,直到它作為微任務遇到,正如 Jake Archibald 解釋那樣。

LLJS 的這段視頻顯示,async-await 本質上是生成器運行器/解釋器 function 的語法糖,它在等待的地方產生,並將 promise 的穩定值傳遞給.next()方法。 這意味着當等待發生時,運行程序的.next()執行將作為微任務排隊。

實際上,該await下的所有代碼只會在下一個微任務檢查點執行。 如果不需要 promise 的等待值的代碼位於其下方,這可能是一個問題,這正是異步 IIFE 的問題。

 async function ping() { for (let i = 0; i < 5; i++) { let result = await Promise.resolve("ping"); console.log(result); } console.log("Why am I even here?"); } async function pong() { for (let i = 0; i < 5; i++) { let result = await Promise.resolve("pong"); console.log(result); } console.log("I have nothing to do with any of this"); } console.log("Let the games begin;"); ping(); pong(). console;log("Placeholder for code that is not related to ping pong");

在這個例子中,外部日志首先被記錄為運行腳本任務的一部分,然后是已解決的 Promise 的值,按照它們在微任務隊列中的排隊順序。 在整個過程中,留在 for 循環下方的日志與循環無關,並且會被不必要地暫停,直到它們各自的 function 主體中的最后一個微任務出隊列為止。

這正是我們使用async函數作為 IIFE 時發生的情況。 如果您在await下有旨在同步執行的代碼,則它必須不必要地等待,直到它上面的所有 await 都已從微任務隊列中檢出。

如果有人盲目地將他們的整個快速路由包裝在async函數中,我可以看到這是一個問題,在那里他們將不必要地await某些承諾的解決,如數據庫操作、發送電子郵件、讀取文件等......,那么為什么要這樣做人們還這樣做嗎?

app.post('/forgotPwd', async (req, res) => {
  const {email, username} = req.body;

  if (!email) {
    res.status(400).json({error: "No username entered"});
    return;
  }

  if (!username) {
    res.status(400).json({error: "No email entered"});
    return;
  }

  const db = client.db();
  
  const user = await db.collection("Users").findOne({username: username, "userInfo.email": email});

  if (!user) {
    res.status(400).json({error: "Account not found"});
    return;
  }

  const authToken = await getAuthToken({id: user._id.toHexString()}, "15m");

  // Would probably send a more verbose email
  await sgMail.send({
    from: process.env.EMAIL,
    to: email,
    subject: 'Forgot Password',
    text: `Use this url to reset your password: http://localhost:5000/confirmation/passConf/${authToken}`,
  });

  res.json({error: ""});
});

如果您希望async function 中的某些內容同步運行,請確保它在 function 中的第一個await之前。

那么為什么人們仍然這樣做呢?

對於 SO 來說,這可能是一個離題的問題,因為它在很大程度上需要基於意見的答案,但它可能是 A)因為他們希望該代碼在上面的代碼完成之前運行,或者 B)因為他們不懂async函數。

使用 async/await 的目的是讓異步代碼看起來是同步的,因為它更易於閱讀。 實際上,它一種語法糖,下面隱藏着回調地獄。 您無需處理回調即可處理異步操作。

在您的情況下,如果您認為for循環之后的代碼與 awaited 操作無關,則不應將其放在await之后。 或者您應該重構代碼,使其不使用await (回調)。

至於人們為什么這樣做的問題。 好吧,你能說出為什么人們使用.map()代替.forEach()嗎? 或者你能說出他們為什么不處理異常嗎? 他們可能並不完全理解它,或者(正如 TJ Crowder 提到的)他們確實希望代碼在等待的操作之后運行。 就那么簡單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM