• async与await


    Generator 函数的语法糖。有更好的语义、更好的适用性、返回值是 Promise

    • await 和 promise 一样,更多的是考笔试题,当然偶尔也会问到和 promise 的一些区别。
    • await 相比直接使用 Promise 来说,优势在于处理 then 的调用链,能够更清晰准确的写出代码。缺点在于滥用 await 可能会导致性能问题,因为 await 会阻塞代码,也许之后的异步代码并不依赖于前者,但仍然需要等待前者完成,导致代码失去了并发性,此时更应该使用 Promise.all。
    • 一个函数如果加上 async ,那么该函数就会返回一个 Promise
    • async => *
    • await => yield
    // 基本用法
    
    async function timeout (ms) {
      await new Promise((resolve) => {
        setTimeout(resolve, ms)    
      })
    }
    async function asyncConsole (value, ms) {
      await timeout(ms)
      console.log(value)
    }
    asyncConsole('hello async and await', 1000)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    下面来看一个使用 await 的代码。

    var a = 0
    var b = async () => {
      a = a + await 10
      console.log('2', a) // -> '2' 10
      a = (await 10) + a
      console.log('3', a) // -> '3' 20
    }
    b()
    a++
    console.log('1', a) // -> '1' 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 首先函数b 先执行,在执行到 await 10 之前变量 a 还是 0,因为在 await 内部实现了 generatorsgenerators 会保留堆栈中东西,所以这时候 a = 0 被保存了下来
    • 因为 await 是异步操作,遇到await就会立即返回一个pending状态的Promise对象,暂时返回执行代码的控制权,使得函数外的代码得以继续执行,所以会先执行 console.log('1', a)
    • 这时候同步代码执行完毕,开始执行异步代码,将保存下来的值拿出来使用,这时候 a = 10
    • 然后后面就是常规执行代码了

    优缺点:

    async/await的优势在于处理 then 的调用链,能够更清晰准确的写出代码,并且也能优雅地解决回调地狱问题。当然也存在一些缺点,因为 await 将异步代码改造成了同步代码,如果多个异步代码没有依赖性却使用了 await 会导致性能上的降低。

    async原理

    async/await语法糖就是使用Generator函数+自动执行器来运作的

    // 定义了一个promise,用来模拟异步请求,作用是传入参数++
    function getNum(num){
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(num+1)
            }, 1000)
        })
    }
    
    //自动执行器,如果一个Generator函数没有执行完,则递归调用
    function asyncFun(func){
      var gen = func();
    
      function next(data){
        var result = gen.next(data);
        if (result.done) return result.value;
        result.value.then(function(data){
          next(data);
        });
      }
    
      next();
    }
    
    // 所需要执行的Generator函数,内部的数据在执行完成一步的promise之后,再调用下一步
    var func = function* (){
      var f1 = yield getNum(1);
      var f2 = yield getNum(f1);
      console.log(f2) ;
    };
    asyncFun(func);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 在执行的过程中,判断一个函数的promise是否完成,如果已经完成,将结果传入下一个函数,继续重复此步骤
    • 每一个 next() 方法返回值的 value 属性为一个 Promise 对象,所以我们为其添加 then 方法, 在 then 方法里面接着运行 next 方法挪移遍历器指针,直到 Generator函数运行完成

  • 相关阅读:
    查看进程时,遇到process information unavailable的解决方法
    《向量数据库指南》——Milvus Cloud 版本迭代的依据的是用户的反馈和对市场趋势的判断
    [山东科技大学OJ]1141 Problem E: 编写函数:有序序列插入数据 之二 (Append Code)
    Spring Boot 2 (四):使用 Docker 部署 Spring Boot
    Vuex中多个参数显示undefined的解决方案
    C#开发的OpenRA游戏之金钱系统(4)
    使用aop注解,实现日志增强,增强方式为前置,后置,环绕
    SpringMVC
    通过文件流转加密压缩文件并下载
    使用iCloud和Shortcuts实现跨设备同步与自动化数据采集
  • 原文地址:https://blog.csdn.net/php_martin/article/details/125856789