Async/Await

参考链接:

async、await 实现原理

async 和 await

1.异步编程回顾

由于 JavaScript 是单线程执行模型,因此必须支持异步编程才能提高运行效率。异步编程的语法目标是让异步过程写起来像同步过程。

异步编程的发展经历了:  回调函数PromiseES7中的async/await

Promise函数在这里不赘述,会另外写一篇Promise的总结,所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

2.async/await

实际上,async/await就是Generator + Promise的语法糖,await必须在async内使用,并装饰一个Promise对象,async返回的也是一个Promise对象。

async 是异步的意思,await 则可以理解为等待。放到一起可以理解async就是用来声明一个异步方法,而 await 是用来等待异步方法执行。

async

async 声明的函数返回一个 Promise 对象,它可以包含多个 await 表达式,这些表达式后面通常跟随着 Promise 对象。当遇到 await 表达式时,async 函数会暂停执行,等待 Promise 对象的状态改变(即 resolvereject,然后恢复执行,并将 resolve 的结果作为 await 表达式的值返回。

所以,对于async关键字,以下两种方法是等效的:

await

而对于await函数,正常情况下,await命令后面是一个Promise对象,返回该对象的结果。如果不是Promise对象,就直接返回对应的值。

在这段代码中,先定义了一个异步函数f,它会返回一个立即resolved的Promise对象,其resolved值为123。然后,通过调用f函数,并使用then方法注册回调函数的方式来获取函数返回的Promise对象。

在异步函数f中:

  • async function 关键字声明了这是一个异步函数,它会返回 Promise 对象,而且在函数中可以使用 await 表达式。
  • return await 123 表示等待 Promise 对象 123 的状态改变(即立即被 resolve),然后将其 resolve 的结果作为函数返回值返回。由于 123 不是一个 Promise 对象,会自动被包装成一个 resolved 状态的 Promise 对象返回,因此其实等价于直接返回 123

因此,这个异步函数 fn1 的返回值实际上就是 Promise.resolve(123),也就是一个立即 resolve 的 Promise 对象,其 resolved 的值为 123

然后这句代码:

f().then(v => console.log(v))
  1. 调用 fn1() 函数,返回一个 Promise 对象。
  2. 使用 then 方法在该对象上注册回调函数,该回调函数的参数 v 就是 Promise 对象 resolve 的值。
  3. 在回调函数中,调用 console.log(v) 打印该值。

示例分析

例1

 

async/await函数的执行顺序:

遇到await时,执行await后面的内容,但是会阻塞下面的代码(即加入微任务队列),先执行 async 外面的同步任务,同步代码执行完,再回到 async 函数中,再执行之前阻塞的代码。

例2:使用 async/await 结合 setTimeout 实现每隔1s 打印一个等于号的功能

async function printEqual() {
  while(true) {
    await new Promise((resolve) => setTimeout(resolve, 1000)) // 等待 1s
    console.log('=')
  }
}

printEqual()

当我们使用 await 关键字等待一个异步函数时,该异步函数必须返回一个 Promise 对象。在这种情况下,await 表达式会暂停当前函数的执行,等待 Promise 对象状态变为 resolved 后恢复执行。同时,由于异步函数本身是不会被阻塞的,因此可以避免阻塞主线程。

在本例中,使用 await 等待了一个 Promise 对象,该 Promise 对象使用 setTimeout 方法创建,实现了一定时间后返回一个 resolved 状态的 Promise,然后通过调用 resolve 函数来设置 Promise 的状态并返回结果。因为 setTimeout 会在一定时间后触发传入的回调函数,所以使用 setTimeout(resolve, 1000) 意味着将在 1 秒后出发 resolve 函数,从而返回一个 resolved 的 Promise 对象。在使用 await 后,程序将会等待 1 秒的时间,然后继续执行 await 之后的代码。

综上所述,await new Promise((resolve) => setTimeout(resolve, 1000)) 表示等待 1 秒钟之后再执行下一步操作,由于是异步的,因此不会阻塞主线程。

 

进阶:只打印100次,不允许使用setInterval

 async function printEquals() {

            for (let count = 0; count < 100; count++) {
                await new Promise((resolve) => setTimeout(resolve, 1000));
                console.log("=");
            }
        }

        printEquals();

追问:这段代码里面的for能不能用forEach代替?

答:不能,因为forEach只支持同步代码,而await是异步操作的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值