【建议点赞收藏】ES系列总结(一)

1,394 阅读4分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

1. Async Await

1.1 简介

ES2015引入了 Promise 来解决“回调地狱”问题,时隔两年,ES2017的 Async-Await 证明Promise不是最终的解决方案

ES2017标准引入了 Async Function 的概念,使得异步操作变得更加方便。Async FunctionGenerator函数的语法糖,从直观上讲就是将Generator 函数的星号(*)替换成async,将 yield 替换成 await

Async Await 比起星号和 yield ,语义更加清晰符合定义,并且 Async Function 函数自带执行器,不需要像 Generator 函数一样调用 next 方法, 或使用co 模块。Async Function 的返回值是Promise对象,await命令则是内部then的语法糖。

1.2 使用

  1. Async 函数中,如果返回一个非Promsie对象,Javascript 会自动将其包装成 Promise.resolve() 的值。

    async function fn() {
      return 'hello _Battle' // 等同于 return Promise.resolve('hello _Battle')
    }
    fn().then((v) => console.log(v)) // 'hello _Battle'
    
  2. 若在Async 函数中抛出错误,会导致返回的Promise对象的状态变为 reject, 从而可以被 catch 捕获。

    async function fn() {
      throw new Error('error')
    }
    fn().then((v) => console.log(v), (err) => console.log(err)) // Error: error
    
  3. await 命令,只能在 async 函数内部使用。 一般情况下,await 命令后接一个 Promise 对象,返回该对象 Fulfilled 后的结果,如果不是,则直接返回对应的值。

    async function test() {
      return await 'hello _Battle' // 等同于 return 'hello _Battle'
    }
    test().then((v) => console.log(v)) // "hello _Battle"
    // 另一种情况,await 接收一个 thenable 对象(具有可调用 then 方法的对象)
    // 这时await会将其等同于Promise对象。
    
    class Thenable {
      constructor(num) {
        this.num = num
      }
      then(resolve, reject) {
        setTimeout(() => resolve(this.num * 2), 1000)
      }
    }
    
    (async () => {
      const res = await new Thenable(5)
      console.log('result:', res)
    })()
    // result:10
    
  4. async-await 错误处理时,任何一个 await 命令后的Promise变为 reject 状态,则会终止 async 函数的执行。

    async function test() {
      await Promise.reject(new Error('error'))
      return await Promise.resolve('hello')
    }
    await test() // Error: error, 后续不会执行
    

    若我们希望即使一个异步操作失败,也不会终止后续执行, 可以用try-catch块单独捕获

    async function test() {
      try {
        await Promise.reject(new Error('error'))  
      } catch (err) {
        console.log(err)
      }
      return await Promise.resolve('hello')
    }
    await test() //1、Error: error; 2、‘hello’
    
  5. 按顺序完成异步操作

    在开发中,常常遇到一组异步操作,需要按顺序输出异步回调的结果。

    Promise 来实现如下:

    将fetch返回的 Promise对 对象放入数组,使用 reduce 方法依次处理每个 Promise 对象,然后使用 then 连接所有 Promise 对象实现顺序输出。

      const logInOrder = (urls) => {
      // 拉取url数组
      const promises = urls.map((item) => {
        return fetch(item).then((res) => res.text())
      }
      promises().reduce((chain, currentPromise) => {
        return chain.then(() => currentPromise).then((text) => console.log('text',text))
      }, Promise.resolve())
      }
    

    async 函数改造

    const logInOrder = async (urls) => {
      for (const url of urls) {
        const res = await fetch(url)
        console.log(await res.text())
      }
    }
    

    上述代码虽然简洁许多, 但是所有 fetch 异步操作都是继发的,原因是async 函数内部的await命令会继发执行, 我们可以对此改造,将外部 urls 的遍历操作提到 async 函数外部,让其并发执行。

    并发改造如下:

    const logInOrder = async (urls) => {
      // 并发远程拉取接口
      const promises = urls.map(async (url) => {
        const res = await fetch(url)
        return res.text()
      })
    }
    // 按顺序输出
    for (const promise of promises) {
      console.log(await promise)
    }
    
  6. 休眠效果

    Javascript 借助 async - await 函数可以让程序停顿指定的时间。

    function sleep (delay) {
      return new Promise((resolve) => {
        setTimeout(resolve, delay)
      })
    }
    (async function test() {
      for (let i = 1; i <= 5; i++) {
        console.log(i)
        await sleep(1000)
      }
    })()
    // 1, 2, 3, 4, 5
    
  7. 使用 try - catch, 实现多次重复尝试

    在开发中,可能因为网络原因导致请求失败, 我们可能需要请求能够重试指定的次数。

    const NUMS = 3
    async function test() {
      let i
      for (i = 0; i < NUMS; ++i) {
        try {
          await fetch('http://google.com/this-throws-an-error')
          break // 若执行成功,终止尝试
        } catch (err) {}    
      }
      console.log(i) // 3
    }
    

点赞支持、手留余香、与有荣焉,动动你发财的小手哟,感谢各位大佬能留下您的足迹。

11.png

往期精彩推荐

前端常用的几种加密方法

canvas 爬坑路【方法篇】

不懂 seo 优化?一篇文章帮你了解如何去做 seo 优化

canvas 爬坑路【属性篇】

【实战篇】微信小程序开发指南和优化实践

聊一聊移动端适配

前端性能优化实战

聊聊让人头疼的正则表达式

获取文件blob流地址实现下载功能

Vue 虚拟 DOM 搞不懂?这篇文章帮你彻底搞定虚拟 DOM

Git 相关推荐

通俗易懂的 Git 入门

git 实现自动推送

我在工作中是如何使用 git 的

面试相关推荐

前端万字面经——基础篇

前端万字面积——进阶篇

更多精彩详见:个人主页