惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
Google DeepMind News
Google DeepMind News
MyScale Blog
MyScale Blog
A
About on SuperTechFans
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
Recent Announcements
Recent Announcements
D
DataBreaches.Net
B
Blog
博客园 - 【当耐特】
爱范儿
爱范儿
有赞技术团队
有赞技术团队
P
Proofpoint News Feed
WordPress大学
WordPress大学
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
I
InfoQ
Engineering at Meta
Engineering at Meta
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Last Week in AI
Last Week in AI
Microsoft Azure Blog
Microsoft Azure Blog
雷峰网
雷峰网
量子位
G
Google Developers Blog

Anthony Fu

Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony's Roads to Open Source - The Set Theory (React ver.) Mental Health in Open Source The Evolution of Shiki v1.0 The Magic in Shiki Magic Move Anthony's Roads to Open Source - The Progressive Path Anthony Fu Anthony Fu Anthony Fu Anthony's Roads to Open Source - The Set Theory Now, and the Future of Nuxt Devtools Anthony's Roads to Open Source - The Set Theory Anthony Fu Anthony Fu Stable Diffusion QR Code 101 Refining AI Generated QR Code Stylistic QR Code with Stable Diffusion Anthony Fu How I Manage GitHub Notifications
Anthony Fu
Anthony Fu · 2021-07-01 · via Anthony Fu

async / await in ES7 is truly a life-saver for the JavaScript world. It allows you to avoid callback hell in your code and make it more readable. However, a common pitfall is that when you await a huge asynchronous task that takes very long time, it blocks the following code and could potentially make your app slow.

For example:

const app = await createServer()
const middlewareA = await resolveMiddlewareA()
const middlewareB = await resolveMiddlewareB()

app.use(middlewareA)
app.use(middlewareB)

We have used three await in the example, while the three async function does not actually relying on each other, having them sequentially we are possibility wasted some time of the operations that could be parallelized (IO, Network, etc.)

So we can use Promise.all to optimize the code:

const [app, middlewareA, middlewareB] = await Promise.all(
  [
    createServer(),
    resolveMiddlewareA(),
    resolveMiddlewareB(),
  ],
)

app.use(middlewareA)
app.use(middlewareB)

In another example, you might relying on the async result, but sometime not that urgent:

async function createPlugin() {
  const toolkit = await initToolKit()

  return {
    onHookA() {
      toolkit.invokeA()
    },
    onHookB() {
      toolkit.invokeB()
    },
  }
}

const plugin = await createPlugin()

Even though you don’t need toolkit immediately, you are still forced to use async function because the initToolKit is async. To avoid this, we could make the promise been resolved in the hooks instead

function createPlugin() {
  const toolkitPromise = initToolKit()

  return {
    async onHookA() {
      const toolkit = await toolkitPromise
      toolkit.invokeA()
    },
    async onHookB() {
      const toolkit = await toolkitPromise
      toolkit.invokeB()
    },
  }
}

// now it's sync!
const plugin = createPlugin()

Since a Promise could only be resolved once, using multiple await for a single Promise instance is totally fine - it will return the resolved result immediate if the Promise is allready settled.

To be more generalized, we could have an utility function like:

export function createSingletonPromise<T>(fn: () => Promise<T>) {
  let _promise: Promise<T> | undefined

  return () => {
    if (!_promise)
      _promise = fn()
    return _promise
  }
}

This function is also available in my utilities collection @antfu/utils