Skip to content

Latest commit

 

History

History
122 lines (94 loc) · 3.03 KB

55.精读《async await 是把双刃剑》.md

File metadata and controls

122 lines (94 loc) · 3.03 KB

55.精读《async await 是把双刃剑》

async 和 await 有可能陷入困境,不是语法的问题,而是使用者书写不当造成的

概述

// 现代前端代码
(async () => {
  const pizzaData = await getPizzaData() // async call
  const drinkData = await getDrinkData() // async call
  const chosenPizza = choosePizza()
  const chosenDrink = chooseDrink()
  await addPizzaToCart(chosenPizza) // async call
  await addDrinkToCart(chosenDrink) // async call
  orderItems() // async call
})()
  • 语法本身并没有问题,当pizzaDatadrinkData依赖的时候,顺序的 await 会最多让执行时间增加一倍的getPizzaData函数时间,因为getPizzaDatagetDrinkData应该并行执行

  • 回到吐槽较多的回调地狱,虽然代码丑,但是不至于两行代码执行有阻塞

  • 语法简化却带来性能问题,直接影响到用户体验

  • 正确做法应该是先同时执行函数,然后再 await 返回值,这样可以并行执行异步函数

    (async () => {
    	const pizzaPromise = selectPizza();
      const drinkPromise = selectDrink();
      await pizzaPromise
      await drinkPromise
    })
    • 或者使用Promise.all,不过可能会让你的代码性能降低

      (async () => {
        Promise.all([selectPizza(), selectDrink()]).then(orderItems) // async call
      })

思考

  • async/ await 被滥用的思考:语法糖带来的便捷 && 牺牲了部分功能

  • 解决问题: 回调地狱

    a(() => {
      b(() => {
        c();
      })
    })
    // to this:
    await a();
    await b();
    await c();
    • 虽然层级一致,但是逻辑还是存在嵌套关系,隐形转换有时候会被忽略导致语法糖的滥用
  • 思考逻辑下的回调场景: 两层同级同步代码嵌套异步代码时的优化

    // a -> b 存在依赖关系 b -> d 存在依赖关系, a / d 可以并发(同步)执行
    a(() => {
      b();
    })
    c(() => {
      d();
    })
    // 翻译
    await a();
    await b();
    await c();
    await d();
    // 优化
    const resA = a();
    const resC = c();
    await resA;
    b();
    await resC;
    d();
    // 相当于完全隔离状态
    (async () => {
      await a();
      b();
    })();
    (async () => {
      await c();
      d();
    })();
    // Promise.all
    async function ab() {
      await a();
      b();
    }
    async function cd() {
      await c();
      d();
    }
    Promise.all([ab(), cd()]);
    • Async/await 写完需要反思一下有没有依赖的异步关系,虽然可读性上去了,但是比回调地狱的性能更低
    • 同步与 await 混杂在一起需要正确使用,必要情况可以使用回调,对增强代码可读性有一定的帮助

summary

  • async/ await 回调地狱提醒我们不要过度依赖新特性,否则会对代码执行效率下降,影响用户体验,同时也不要过度利用新特性修复新特性带来的问题,这样反而导致代码可读性的下降
  • 决定代码质量的是思维,并非框架或语法, async/await 虽然好,但是也要适度使用。