async / await 详解

async / await 作用

async/await 是 Promise 的语法糖(await 是 then 的语法糖),通过同步的方式执行异步任务

以下用一个对比来说明以下

现在我们要实现一个红绿灯的效果,通过异步任务依次输出 绿、黄、红 (时间的模拟暂时不考虑) 如果用传统的 Promise 实现:

Promise.resolve('绿').then((res) => {
  console.log(res)

  Promise.resolve('黄').then((res) => {
    console.log(res)

    Promise.resolve('红').then((res) => {
      console.log(res)
    })
  })
})

我们可以用 async/await 来实现一下:

// 立即执行函数
(async () => {
  await Promise.resolve('绿').then(res => console.log(res))
  await Promise.resolve('黄').then(res => console.log(res))
  await Promise.resolve('红').then(res => console.log(res))
})()

通过前后对比,我们可以发现,在需要异步任务按照顺序严格执行的情况下, async/await 可以避免嵌套过多的情况,取而代之的是简单易懂的同步形式代码。

async / await 基础使用

  • async 表示这是一个 async 函数(即普通函数变成了异步函数), await 只能用在 async 函数里面,不能单独使用
    // 单独使用 await 报错
    (function(){
        await Promise.resolve('Jasmine')   
    })()
    // Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
  • async 返回的是 Promise 成功的对象,await 就是等待这个 promise 的返回结果后,再继续执行(这句怎么理解?执行顺序里解释)。有无 resolve,取决于函数中有无 return 值。
  • // 在函数中没有 return 值,故无 resolve
    (async function(){
        await Promise.resolve('Jasmine')  
    })()
    // Promise {<fulfilled>: undefined}
    
    // 在函数中有 return 值,故有 resolve
    (async function(){
        return await Promise.resolve('Jasmine')   
    })()
    // 888
    // Promise {<fulfilled>: 'Jasmine'}
  • await 等待的是一个 Promise 对象,后面必须跟一个 Promise 对象,但是不必写 then(),直接就可以得到返回值,如果不是,则会包裹一层 Promise.resolve()
    // await 后面不是 Promise,则会包裹一层 Promise.resolve()
    (async function(){
        return await 666
    })()
    // Promise {<fulfilled>: 666}

如果发生异常,怎么处理?

可以使用 try/catch 来捕获异常,把 await 放到 try 中进行执行,如有异常,就使用 catch 进行处理。

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

async / await 存在时的执行顺序

async function 内部的 await 表达式之后的代码块会在下一个微任务中执行

案例 1
(async () => {
  setTimeout(() => {
    console.log('after 0s')
  }, 0)

  new Promise((resolve) => {
    resolve('我是微任务啦')
  }).then((res) => {
    console.log(res)
  })

  console.log('我是同步任务哎')
  
  await new Promise((resolve) => {
    resolve("我成功喽")
  }).then((res) => {
    console.log(res)
  });

  new Promise((resolve) => {
    resolve('我是await之后的微任务啦')
  }).then((res) => {
    console.log(res)
  })

  console.log('我是await之后的同步任务啦')
})()

// 我是同步任务哎
// 我是微任务啦
// 我成功喽
// 我是await之后的同步任务啦
// 我是await之后的微任务啦
// after 0s

执行顺序如上注释。我们用事件循环机制来分析

按照以上描述,事件循环队列中的任务如下:

案例 2

将案例1改造一下,await new Promise 里面包个定时器

(async () => {
  setTimeout(() => {
    console.log('after 0s')
  }, 0)

  new Promise((resolve) => {
    resolve('我是微任务啦')
  }).then((res) => {
    console.log(res)
  })

  console.log('我是同步任务哎')
  
  await new Promise((resolve) => {
    setTimeout(function(){
        resolve("我成功喽")
    }, 0)
  }).then((res) => {
    console.log(res)
  });

  new Promise((resolve) => {
    resolve('我是await之后的微任务啦')
  }).then((res) => {
    console.log(res)
  })

  console.log('我是await之后的同步任务啦')
})()

// 我是同步任务哎
// 我是微任务啦
// after 0s
// 我成功喽
// 我是await之后的同步任务啦
// 我是await之后的微任务啦

执行顺序如上注释。事件循环队列中的任务变为如下:

总结
  • 当遇到 await,会先暂停 await 及后边代码的执行,直到 Promise 的状态发生改变后,才会继续执行 await 以及后边的任务
  • await 本质是 then 的语法糖,其实是个微任务
  • 在 await new Promise 中如果包含一个定时器,定时器的回调函数中写 resolve() 或者reject(),那么这个定时器是个宏任务,会在宏任务队列排队完成后,再改变 Promise 的状态,然后 await 才能执行,再取消阻塞
  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
async/await是JavaScript中处理异步编程的一种方法。它是Generator函数的语法糖,能够更方便地编写和管理异步代码。通过使用async关键字来声明一个函数是异步的,并使用await关键字来等待一个异步操作完成,可以使异步代码的执行像同步代码一样顺序进行,避免了回调地狱的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [javascript中async/await详解](https://blog.csdn.net/abxxcd/article/details/108226045)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [JavaScript async / await详解](https://blog.csdn.net/Niall_Tonshall/article/details/122669264)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [async/await详解](https://blog.csdn.net/qq_38951259/article/details/127973287)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘子味的冰淇淋~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值