• ES6系列 (05):async await


    首先我们先来了解几个async基本知识点:

    await命令只能用在async函数之中,如果用在普通函数,就会报错

    async函数返回的是Promise 对象

    • 如果返回的是一个基本类型数据,async函数会先用Promise.resolve(...)将其包装为一个Promise对象再将其返回。
    • 如果无返回值,等同于直接返回Promise.resolve()
    • 如果返回的是一个Promise对象,则不做处理直接将其返回

    await命令后面可跟Promise对象或者任意表达式

    • 如果是Promise对象,则等待并返回该对象的结果
    • 如果是表达式,则等待并返回表达式的值

    错误处理

    如果await 后面的Promise对象变为rejected状态 或者 async方法抛出异常,那么整个async函数则会中断执行,并且返回的 Promise 对象为rejected状态

    • Promise对象变为rejected状态:

      async function getTodo() {
         await new Promise(function (resolve, reject) {
           reject('异步操作出错了')
         })
         console.log('柏成大帅比')
         return '柏成'
      }
      
      getTodo().then(res => console.log('res',res))
        .catch(err => console.log('err',err))
      
      // err,异步操作出错了
      
    • async方法抛出异常:

      async function getTodo() {
        await new Promise(function (resolve, reject) {
          resolve('异步操作正常')
        })
        throw new Error('代码抛出异常')
        console.log('柏成大帅比')
        return '柏成'
      }
      
      getTodo().then(res => console.log('res',res))
        .catch(err => console.log('err',err))
      
      // err,Error: 代码抛出异常
      // at getTodo (js012-测试.html:11)
      

    为了防止代码异常阻塞async函数的执行,我们可以使用try...catch方法, 如果try方法块中Promise对象变为rejected状态 或者 代码抛出异常,则仅仅中断try方法块的代码执行,并不会阻塞async函数的后续代码执行

    async function getTodo() {
      try {
        const val1 = await getFirstVal()
        const val2 = await getSecondVal()
        const val1 = await new Promise(function (resolve, reject) {
          reject('异步操作异常')
        })
      } catch (err) {
        console.log(err);
      }
      console.log('柏成大帅比')   
      return 'hello world'
    }
    
    getTodo().then(res => console.log(res))
    .catch(err => console.log(err))
    
    // 异步操作异常
    // 柏成大帅比
    // hello world
    

    实现休眠语法

    记得之前做课设要实现一个着色格子板,要看到着色的过程,如何在本次着色后暂停一秒钟再执行下一次着色代码,就采用了下面的休眠方法

    // 休眠方法 
    function sleep(interval) {
      return new Promise(resolve => {
        setTimeout(()=> resolve(), interval);
      })
    }
    
    // 调用休眠方法
    (async function () {
      for(let i = 1; i <= 5; i++) {
        console.log(i)
        await sleep(1000)
      }
    })()
    

    继发&并发

    继发执行:异步操作存在先后顺序,等待上一个 await 执行完毕后,再接着下一个

    async function getTodo() {
      const val1 = await getFirstVal()
      const val2 = await getSecondVal()
    }
    

    并发执行:异步操作相互独立,不存在依赖关系,可以同时触发,提高执行效率

    // 如没有await关键字,遇到异步操作,将其挂起无需等待异步操作结果,转而继续执行下一行代码,基本等同于同时触发
    const firstPromise = getFirstVal()  
    const secondPromise = getSecondVal()   
    const [val1, val2] = await Promise.all([firstPromise, secondPromise]);
    
    // 或者
    
    const [val1, val2] = await Promise.all([getFirstVal(), getSecondVal()]);
    

    循环中的await

    for语句、for/in语句、for/of语句,会继发执行(等待上一个 await 执行完毕后,再接着下一个),没有任何叼毛问题,nice!

    async function getTodo(arr) {
      for (const item of arr) {
        const res = await getSomething(item);
        console.log(`res-${item}:`, res);
      }
    
      console.log('finished!');
    }
    
    getTodo([1,2,3])
    
    // res-1:...
    // res-2:...
    // res-3:...
    // finished!
    

    forEachmap,调用了callback回调函数,存在大大的副作用,强烈不建议在forEachmap等循环中使用await

    async function getTodo(arr) {
      await arr.forEach(async item => {
        const res = await getSomething(item);
        console.log(`res-${item}:`, res);
      })
    
      console.log('finished!');
    }
    
    getTodo([1,2,3])
    
    // finished!
    // res-2:...
    // res-1:...
    // res-3:...
    

    从上面代码中我们可以看出两个问题

    • 尽管我们在forEach循环之前使用了await,但是他不会等待forEach循环的执行,而是直接打印finished!

    • 三个getSomething()异步操作将是并发执行,请求时间短的操作将被率先打印,和请求顺序无关

    参考文档

    阮一峰 async函数
    for 循环里的 await

    人间不正经生活手册
  • 相关阅读:
    setTimeout,clearTimeout,setInterval,clearInteral详解
    关于JS读取DOM对象(标签)的自定义属性
    jquery.form.js官方插件介绍Form插件,支持Ajax,支持Ajax文件上传
    按回车键切换input鼠标光标
    电压跟随器的作用,以及其中两个电阻的作用?
    阅读RB521S30肖特基二极管的datasheet
    配置linux内核,解决lcd logo和十分钟息屏!
    配置linux,关闭LCD的console控制台输出。
    记录一次编译linux内核或者说编译dtbs的问题!!
    copy_from_user的详细用法!
  • 原文地址:https://www.cnblogs.com/burc/p/14136046.html
Copyright © 2020-2023  润新知