定义

async作为一个关键字放在函数前面,表示该函数是一个异步函数,异步函数意味着该函数的执行不会阻塞后面代码的执行;而 await 用于等待一个异步方法执行完成;
async/await的作用就是使异步操作以同步的方式去执行

一. 关于async

async的用法,语法很简单,在函数前面加上async关键字,表示函数是异步的。

 async function timeout() {return 'hello world!'}

只有一个作用,他的调用会返回一个promise对象。
那怎么调用呢?async 函数也是函数,平时我们怎么使用函数就怎么使用它,直接加括号调用就可以了,为了表示它没有阻塞它后面代码的执行,我们在async 函数调用之后加一句console.log;

 async function timeout() {return 'hello world!'}timeout()console.log('我虽然在后面,但是先执行')

打印结果:

发现 timeout() 函数虽然调用了,但是没打印 hello world!; 先不要着急, 看一看timeout() 返回了什么? 把上面的 timeout() 语句改为console.log(timeout())

打印结果:

原来async 函数返回的是一个promise 对象,并且Promise还有state和result,如果async函数中有返回值,当调用该函数时,内部会调用Promise.resolve()方法把它转化成一个promise对象作为返回,但如果timeout函数内部抛出错误呢? 那么就会调用Promise.reject() 返回一个promise 对象

async function timeout() {throw new Error('rejected');
}
console.log(timeout());

就会调用Promise.reject() 返回一个promise 对象
 
那么要想获取到async 函数的执行结果,就要调用promise的then 或 catch 来给它注册回调函数

继续修改代码

  async function timeout() {return 'hello world!'}timeout().then(val => {console.log(val)})console.log('我虽然在后面,但是先执行')

打印结果:

我们获取到了"hello world!', 同时timeout的执行也没有阻塞后面代码的执行,和 我们刚才说的一致。
 
如果async 函数执行完,返回的promise 没有注册回调函数,比如函数内部做了一次for 循环,你会发现函数的调用,就是执行了函数体,和普通函数没有区别,唯一的区别就是函数执行完会返回一个promise 对象。

   async function timeout () {for (let index = 0; index < 3; index++) {console.log('async', +index)}}console.log(timeout())console.log('outer')

二. 关于await

1) await 到底在等啥?

async 关键字差不多了,最重要的就是async函数的执行会返回promise对象,并且把内部的值进行promise的封装。如果promise对象通过then或catch方法又注册了回调函数,async函数执行完以后,注册的回调函数就会放到异步队列中,等待执行。
如果只是async,和promise差不多,但有了await就不一样了,await关键字只能放到async函数里面,await是等待的意思,那么它等待什么呢?它后面跟着什么呢?其实await不仅仅用于等Promise对象,还可以等任意表达式,所以await后面实际是可以接普通函数调用或者直接量的,不过我们更多的是放一个返回promise 对象的表达式。他等待的是promise对象执行完毕,并返回结果。

//所以下面这个示例完全可以正确运行function getSomething () {return 'something'}async function testAsync () {return Promise.resolve('hello async')}async function test () {const v1 = await getSomething()const v2 = await testAsync()console.log(v1, v2)}test()

2) await 等到了要等的,然后呢?

await 等到了它要等的东西,一个 Promise 对象,或者其它值,然后呢?

  1. 如果它等到的不是一个Promise对象,那么await表达式的运算结果就是它等到的东西。
  2. 如果它等到的是一个Promise对象,await就忙起来了,它会阻塞函数后面的代码,等着Promise对象resolve,然后得到resolve的值,作为await表达式的运算结果。

3) async/await 帮我们干了啥?

做个简单的比较
现在举例,用 setTimeout 模拟耗时的异步操作,先来看看不用 async/await 会怎么写

function takeLongTime () {return new Promise(resolve => {setTimeout(() =>resolve('long_time_value'), 1000)})}
takeLongTime().then(val => {console.log(val, 'val')
})

如果改用 async/await 呢,会是这样

    function takeLongTime () {return new Promise(resolve => {setTimeout(() =>resolve('long_time_value'), 1000)})}async function test () {let v = await takeLongTime()console.log(v, 'v')}test()

眼尖的已经发现 takeLongTime () 没有申明为async。实际上takeLongTime () 本身就返回Promise对象,加不加async结果都一样。

4) await 优势在于处理 then 链,使代码看起来像同步代码一样,下面是实例应用

现在写一个函数,让它返回promise 对象,该函数的作用是2s 之后让数值乘以2

// 2s 之后返回双倍的值
function doubleAfter2seconds (num) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(num * 2)}, 2000)})}

现在再写一个async 函数,从而可以使用await 关键字, await 后面放置的就是返回promise对象的一个表达式,所以它后面可以写上 doubleAfter2seconds 函数的调用

async function testResult() {let result = await doubleAfter2seconds(30);console.log(result); //2s后打印60
}
testResult();

代码的执行过程
调用testResult 函数,它里面遇到了await, await 表示等待,代码就暂停到这里,不再向下执行了,它等待后面的promise对象执行完毕,然后拿到promise resolve 的值并进行返回,返回值拿到之后,它继续向下执行。具体到 我们的代码, 遇到await 之后,代码就暂停执行了, 等待doubleAfter2seconds(30) 执行完毕,doubleAfter2seconds(30) 返回的promise 开始执行,2秒 之后,promise resolve 了, 并返回了值为60, 这时await 才拿到返回值60, 然后赋值给result, 暂停结束,代码继续执行,执行 console.log语句。

就这一个函数,我们可能看不出async/await 的作用,如果我们要计算3个数的值,然后把得到的值进行输出呢?

async function testResult() {let first = await doubleAfter2seconds(30);let second = await doubleAfter2seconds(50);let third = await doubleAfter2seconds(30);console.log(first + second + third);
}
testResult()

6秒后,控制台输出220, 我们可以看到,写异步代码就像写同步代码一样了,再也没有回调地域了。

这里强调一下,当js引擎在等待promise.resolve的时候,他并没有真正的暂停工作,它可以处理其他的一些事情,如果我们在testResult函数后面继续执行其他代码,比如console.log一下,会发现console.log代码先执行。

async function testResult() {let first = await doubleAfter2seconds(30);let second = await doubleAfter2seconds(50);let third = await doubleAfter2seconds(30);console.log(first + second + third);
}
testResult()
console.log('我先执行!!!')

先输出 “我先执行!!!”,6s后输出计算结果。

总结:

  1. async 函数
    1)函数的返回值为Promise对象
    2)Promise对象的结果由async函数执行的返回值决定
  2. await 表达式
    1)await右侧的表达式一般为promise对象, 但也可以是其它的值
    2)如果表达式是promise对象,await就忙起来了,它会阻塞函数后面的代码,等着Promise对象resolve,然后得到resolve的值,作为await表达式的运算结果。
    3)如果表达式是其它值, 直接将此值作为await的返回值
  3. asyncawait基于promise的。使用async的函数将会始终返回一个 promise 对象。这一点很重要,要记住,可能是你遇到容易犯错的地方。
  4. 在使用await的时候我们只是暂停了函数,而非整段代码。
  5. async和await是非阻塞的
  6. 仍然可以使用 Promise,例如Promise.all().
  7. 注意
    1)await必须写在async函数中, 但async函数中可以没有await
    2)如果await的promise失败了, 就会抛出异常, 需要通过try…catch来捕获处理

下一篇:理解js中的同步和异步

学习过程中参考了:
用 async/await 来处理异步
vue中异步函数async和await的用法
理解 JavaScript 的 async/await

理解异步函数async和await的用法相关推荐

  1. vue中异步函数async和await的用法

    先说一下async的用法,它作为一个关键字放到函数前面,用于表示函数是一个异步函数,因为async就是异步的意思, 异步函数也就意味着该函数的执行不会阻塞后面代码的执行. 写一个async 函数 as ...

  2. ES2017 异步函数async/await

    ES2017标准已于2017年6月份正式定稿了,并广泛支持最新的特性:异步函数.如果你曾经被异步 JavaScript 的逻辑困扰,这么新函数正是为你设计的. 异步函数或多或少会让你编写一些顺序的 J ...

  3. js异步函数(async/await)

    1.概念 异步函数也称为"asynac/await"(语法关键字),是ES6期约模式在ECMAScript函数中的应用.async/await是ES8新增的.这个特性让以同步方式写 ...

  4. async 与 await 的用法详解

    文章出自个人博客https://knightyun.github.io/2019/08/02/js-async-await,转载请申明 async 概念 用于声明异步函数,返回值为一个 Promise ...

  5. async和await的用法

    一.async&await用法 async 表示函数里有异步操作, await 表示紧跟在后面的表达式需要等待结果. 同 Generator 函数一样,async 函数返回一个 Promise ...

  6. 一个简单的实例帮你彻底学会async和await的用法

    首先我相信很多人都知道async和await,并且知道他们可以解决异步问题,比如请求一个接口,我们下面的同步操作需要等这个接口的返回值做判断,一般我们就直接写在成功的回调里面,但是如果请求接口很多,那 ...

  7. C# 中的Async 和 Await 的用法详解

    众所周知C#提供Async和Await关键字来实现异步编程.在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await. 同样本文的内容也大多是翻译 ...

  8. 【转载】 C# 中的Async 和 Await 的用法详解

    众所周知C#提供Async和Await关键字来实现异步编程.在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await. 同样本文的内容也大多是翻译 ...

  9. 常见的异步方式async 和 await

    之前研究过c#的async和await关键字,幕后干了什么,但是不知道为什么找不到相关资料了.现在重新研究一遍,顺便记录下来,方便以后查阅. 基础知识 async 关键字标注一个方法,该方法返回值是一 ...

最新文章

  1. 数组对称_对称性应用在物理中的几个小例子
  2. mpvue开发小程序所遇问题及h5转化方案
  3. 高可用集群技术之RHCS应用详解(一)
  4. SCGHR_存储过程(eSP_IDChangeStart)_政治面貌为什么不能正确更新
  5. 以太坊solidity编程常见错误(不定期更新)
  6. js页面排序-----基础篇
  7. swift 可变參数
  8. android 覆盖安装问题
  9. 总有人黑 JavaScript?那是不知道它有多好用吧!
  10. EXCEL 制作万年历
  11. java 微信 jssdk 分享朋友圈_微信JS-sdk分享到朋友圈无效
  12. iris数据集——决策树
  13. java母类_java关键字分类详解
  14. YY创始人携手极客公园调坎QQ企鹅
  15. geom_segment 新技能get
  16. 计算机二级模板文档,江苏省计算机二级
  17. python 50 前端 html5 css3
  18. spark+mongodb大数据框架搭建
  19. 【雷达原理】FMCW雷达简介
  20. 贴片电容COG、NPO 、X7R、X5R、Y5V介质区别

热门文章

  1. 如果国产手机都用鸿蒙,华为自己都不用鸿蒙,那么会有哪个国产手机品牌会使用?...
  2. sentinel 集群限流
  3. week1模拟与高精度
  4. 抖音直播带货推流机制是什么?怎么跑好直播带货30分钟循环过款模型?
  5. 计算机基础及软件测试学习路线
  6. golang把数字变字符串_Golang - 数字转字符串
  7. linux之关机、重启命令
  8. 字符串排序(C语言实现)
  9. 好玩的网站 可以实时看到任意航班的实时情况 位置 高度
  10. 第四阶段--Spring学习-03