阿八博客
  • 100000+

    文章

  • 23

    评论

  • 20

    友链

  • 最近新加了很多技术文章,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

异步编程之 async/await 函数

欢迎来到阿八个人博客网站。本 阿八个人博客 网站提供最新的站长新闻,各种互联网资讯。 喜欢本站的朋友可以收藏本站,或者加QQ:我们大家一起来交流技术! URL链接:https://www.abboke.com/jsh/2019/0919/114032.html
提起异步编程,大家可能会想到事件监听、回调函数、发布订阅、Promise 对象、Generator 函数、async 函数等,本篇主要讲解的是 async 函数,很多人认为它是异步编程的终极解决方案

一、async 函数是什么?

摘自阮老师的文章:一句话,它就是 Generator 函数的语法糖;也有人说它是 Promise 的语法糖

如果你对 Promise 对象、 Generator 函数不是特别了解的话,建议先看一下阮老师 ECMAScript6 入门中的关于 Promise 对象 和 Generator 函数的介绍

二、async

1.async 声明的函数的返回本质上是一个 promise 对象(很重要


就是说只要你声明了这个函数是 async,那么内部不管你怎么处理,它的返回肯定是个 Promise

async function myAsync () {   return 'hello world'}let result = myAsync()console.log(result)

3.async 函数返回的 Promise 对象,必须等到内部所有 await 命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到 return 语句或者抛出错误

也就是说,只有 async 函数内部的异步操作执行完,才会执行 then 方法指定的回调函数

function getNum () {  return new Promise((resolve) => {    setTimeout(() => {      resolve(1000)    }, 1000)  })}async function myAsync () {  let num = await getNum()  return num + 1000}myAsync().then((val) => {  console.log(val)})

上面代码中,函数 myAsync 内部有两个操作:获取 num,加 1000 后并返回结果
只有这两个操作全部完成,才会执行 then 方法里面的 console.log(val)

三、await

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

2.await 的意思就是让 JavaScript 引擎等待,直到 await 命令后代码执行完毕,然后继续执行 await 命令后面的代码

3.这个行为不会耗费 CPU 资源,因为引擎可以同时处理其他任务:执行其他脚本,处理事件等

我们来看个例子,可以试着写出执行结果

function myAwait () {   return new Promise((resolve) => {     resolve('hello world!')   })}async function myAsync(){   console.log('async begin')   let wait = await myAwait()   console.log(wait)   console.log('async end')   return wait}console.log('begin')let result = myAsync()console.log(result)console.log('end')

对比以上三种实现方式:

1.由于 Promise 的 then 方法返回的是一个新的 Promise,所以 Promise 可以通过链式调用实现异步编程

2.async 函数和 Generator 函数就比较有意思了,async 函数就是将 Generator 函数的星号(*)替换成 async,将 yield 替换成 await,并内置执行器,仅此而已

3.不难发现,async 的写法更具语义化,并且更加清晰

五、使用注意事项

1.await 命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await命令放在 try...catch 代码块中

async function myFunction() {  try {    await somethingThatReturnsAPromise();  } catch (err) {    console.log(err);  }}// 另一种写法async function myFunction() {  await somethingThatReturnsAPromise()  .catch(function (err) {    console.log(err);  });}

2.多个 await 命令后面的异步操作,如果不存在继发关系,最好让它们同时触发

function getA () {  return new Promise((resolve) => {    setTimeout(() => {      resolve('A')    }, 1000)  })}function getB () {  return new Promise((resolve) => {    setTimeout(() => {      resolve('B')    }, 1000)  })}async function myAsync () {  let A = await getA();  console.log('A: ', A)  let B = await getB();  console.log('B: ', B)}myAsync()

上面代码中,getA 和 getB 是两个独立的异步操作(即互不依赖),被写成继发关系
这样比较耗时,因为只有 getA 完成以后,才会执行 getB,完全可以让它们同时触发

// 写法一async function myAsync () {  let [A, B] = await Promise.all([getA(), getB()])  console.log('A: ', A)  console.log('B: ', B)}myAsync()
// 写法二async function myAsync () {  let aPromise = getA()  let bPromise = getB()  let A = await aPromise  let B = await bPromise  console.log('A: ', A)  console.log('B: ', B)}myAsync()

上面两种写法,getA 和 getB 都是同时触发,这样就会缩短程序的执行时间

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

六、小结

函数前面的关键字 async 有两个作用:

1.让这个函数返回一个 promise
2.允许在函数内部使用 await,这个 await 关键字又让 JavaScript 引擎等待直到 promise 完成,如果有错误,就会抛出异常,否则,就返回结果

这两个关键字一起用就提供了一个通俗易懂的方式来控制异步编程,并且易于读写

七、附加题:async、promise、setTimeout 的执行顺序

相信你对 Promise、Generator、async 已经有了一定的了解了,若加上 setTimeout,你对代码的执行顺序还很清晰吗?

我们来看一道写出执行结果的题,相信很多同学面试的时候都遇到过,是不是很懵逼!!!

async function async1() {   console.log('async1 start')   await async2()   console.log('async1 end')}async function async2() {   console.log('async2')}console.log('script start')setTimeout(() => {    console.log('setTimeout')},0)async1()new Promise((resolve) => {    console.log('promise1')    resolve()}).then(() => {    console.log('promise2')})console.log('script end')

执行结果(不同浏览器执行结果可能不同,下面结果用的谷歌):

相关文章

暂住......别动,不想说点什么吗?
  • 全部评论(0
    还没有评论,快来抢沙发吧!