1、初识 async 函数
ES6中提供了两个很好的解决异步操作的方案 Promise 和 Generator,ES2017标准中引入的 async 函数就是建立在 Promise 和 Generator的基础之上,它是 Generator函数的语法糖,使异步操作更加方便
先通过一个异步读取文件的小栗子来对比下Promise、Generator 和 async 的异同点
const fs = require('fs')function readFile(fileName) {return new Promise((resolve, reject) => {fs.readFile(fileName, (err, data) => {if(err) {reject(err)}resolve(data.toString())})})
}

(1)、通过 Promise 读取文件
readFile('data/a.txt').then(res => console.log(res)).catch(err => console.log(err))readFile('data/b.txt').then(res => console.log(res)).catch(err => console.log(err))readFile('data/c.txt').then(res => console.log(res)).catch(err => console.log(err))

(2)、通过 Generator 函数读取文件
与 Promise 相比较,优点:把所有的接口都封装在一个函数里面了,缺点:代码量稍微多一点点
function* gen() {yield readFile('data/a.txt')yield readFile('data/b.txt')yield readFile('data/c.txt')
}let it = gen()it.next().value.then(res => {console.log(res)
}).catch(err => {console.log(err)
})it.next().value.then(res => {console.log(res)
}).catch(err => {console.log(err)
})it.next().value.then(res => {console.log(res)
}).catch(err => {console.log(err)
})

(3)、通过 async 函数读取文件
充分吸取了 Promise 和 Generator的优点,同时避免了它们的缺点
async function read() {let readA = await readFile('data/a.txt')let readB = await readFile('data/b.txt')let readC = await readFile('data/c.txt')console.log(readA)console.log(readB)console.log(readC)
}read()

最终的输出结果

通过上例可以看出,async 函数就是将 Generator函数的星号("*")替换成了 async,把 yield 替换成了 await
async 函数对 Generator函数的改进,主要体现在三个方面:
(1)、内置执行器
async函数的执行,与普通函数一模一样,只需一行;而 Generator函数,需要调用next 方法
(2)、返回值是 Promise
async函数的返回值是Promise,这比 Generator函数返回一个 Iterator对象方便多了
(3)、更好的语义化
从字面意思上来讲,async是英文单词 asynchronous 的缩写,表示异步的;await中的 wait 是等待的意思。
因此相比 Generator函数中的星号和yield,语义更加清楚,async 表示这是一个异步操作的函数,await 表示紧跟在后面的表达式需要等待结果
2、async 函数的多种使用形式
// 函数声明
async function foo() {// ....
}// 函数表达式
let foo = async function() {// ....
}// 箭头函数
let foo = async() => {}// 对象的方法
let obj = {name: 'Roger',async foo() {}
}
obj.foo().then(res => {// ....
})// 类的方法
class Student{constructor(name, age) {this.name = namethis.age = age}async say() {return `My name is ${this.name}, I'm ${this.age} years old !`}
}let jim = new Student('Jim Green', 13)
jim.say().then(res => console.log(res))   // My name is Jim Green, I'm 13 years old !

3、基本用法
async 函数返回一个 Promise 实例对象,可以使用 then 方法添加回调函数。
当函数执行时,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句
// 休眠 ms 毫秒
function sleep(ms) {return new Promise(resolve => {setTimeout(resolve, ms)})
}async function print(ms) {console.log('start... ...')await sleep(ms)console.log('end... ...')
}print(1000)

(1)、async 函数内部 return语句返回的值,会成为then方法回调函数的参数
async function foo() {return 'hello world'
}foo().then(res => console.log(res))   // hello world

(2)、async 函数内部抛出错误,会导致返回的 Promise对象变成reject状态,抛出的错误会被catch方法回调函数接收到
async function bar() {return new Error('Error... ...')
}bar().then(res => console.log(res)).catch(err => console.log(err))   // Error: Error... ...

(3)、只有 async 函数内部的异步操作执行完,才会执行 then方法指定的回调函数
async function baz() {await new Promise(resolve => {console.log('执行第一个异步操作')setTimeout(resolve, 2000)})await new Promise(resolve => {console.log('执行第二个异步操作')setTimeout(resolve, 3000)})return '异步执行完毕再执行then方法'
}baz().then(res => {console.log(res)})

4、await 命令
await 用于等待一个 Promise对象,它只能在一个 async函数中使用
[return_value] = await expression表达式:一个 Promise对象或者任何要等待的值返回值:返回 Promise对象的处理结果。如果等待的不是 Promise对象,则返回该值本身

await命令会暂停当前 async函数的执行,等待 Promise处理完成。如果 Promise正常处理,其回调的 resolve函数参数会作为 await表达式的返回值,继续执行 async函数。如果 Promise处理异常,await表达式会把 Promise的异常原因抛出
// 如果 await 命令后的表达式的值不是一个 Promise,则返回该值本身
async function foo() {return await 123
}foo().then(res => console.log(res))    // 123// 如果 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的返回值
async function bar() {let f = await new Promise((resolve, reject) => {resolve('我是表达式的返回值')})console.log(f)   // 我是表达式的返回值return 'ending'
}bar().then(res => {console.log(res)})    // ending// 如果 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出
async function baz() {await new Promise((resolve, reject) => {reject(new Error('出错啦......'))})
}baz().then(res => console.log(res)).catch(err => console.log(err))     // Error: 出错啦......

(1)、任何一个 await语句后面的 Promise对象变为 reject状态,那么整个 async函数都会中断执行
async function foo() {await Promise.reject('error')return 'ending'   // 未执行
}foo().then(res => console.log(res))
// Uncaught (in promise) error

(2)、如果希望当前面的异步操作失败时,不要中断后面的异步操作,可以把前面的 await放在try...catch结构里面
async function foo() {try{await Promise.reject('error')} catch(e) {}return await Promise.resolve('执行完毕')
}foo().then(res => console.log(res))    // 执行完毕

还可以在 await后面的 Promise对象再跟一个 catch方法,处理前面可能出现的错误
async function foo() {await Promise.reject('error').catch(err => console.log(err))return '执行完毕'
}foo().then(res => console.log(res))    // 执行完毕

(3)、如果想让多个异步操作同时触发,缩短程序的执行时间,可以参考如下两种写法
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;

转载于:https://www.cnblogs.com/rogerwu/p/10784236.html

JS异步操作新体验之 async函数相关推荐

  1. 【JS】930- 更快的 async 函数和 promises

    作者:语雀 链接:https://www.yuque.com/es2049/blog/yfqmu1 原文链接:https://v8.dev/blog/fast-async JavaScript 的异步 ...

  2. 【ES6】异步操作和async函数

    [ES6]异步操作和async函数 一.基本概念 二.回调函数 三.Promise 四.async函数 查看更多ES6教学文章: 参考文献 引言:ES6新增的Generato.Promise.asyn ...

  3. 【前端学习之路】ES6新特性 Promise基本方法 、async函数(阮一峰老师、小马哥_老师 课程笔记)

    1.Promise.then()方法 Promise 实例具有 then 方法,其第一个参数是 resolve 状态的回调函数,第二个参数是 reject 状态的回调函数,它们是可选的. then 方 ...

  4. es6 async函数实例:按顺序完成异步操作

    async函数实例:按顺序完成异步操作 实际开发中,经常遇到一组异步操作,需要按照顺序完成.比如,依次远程读取一组 URL,然后按照读取的顺序输出结果. ES6 Promise 的写法如下. func ...

  5. async 函数——JS中的异步处理方式

    async 函数的语法 async function name([param[, param[, ... param]]]) { statements } name: 函数名称. param: 要传递 ...

  6. JS async 函数

    async 函数 含义 ES2017 标准引入了 async 函数,使得异步操作变得更加方便. async 函数是什么?一句话,它就是 Generator 函数的语法糖. 生成器 function* ...

  7. 阮一峰老师的ES6入门:async 函数

    async 函数 1. 含义 ES2017 标准引入了 async 函数,使得异步操作变得更加方便. async 函数是什么?一句话,它就是 Generator 函数的语法糖. 前文有一个 Gener ...

  8. 用Async函数简化异步代码

    Promise 在 JavaScript 上发布之初就在互联网上流行了起来 - 它们帮开发人员摆脱了回调地狱,解决了在很多地方困扰 JavaScript 开发者的异步问题.但 Promises 也远非 ...

  9. 用 Async 函数简化异步代码

    Promise 在 JavaScript 上发布之初就在互联网上流行了起来 - 它们帮开发人员摆脱了回调地狱,解决了在很多地方困扰 JavaScript 开发者的异步问题.但 Promises 也远非 ...

最新文章

  1. 比特币现金的第四次战役
  2. JavaScript中的继承入门
  3. poj 1753 Flip Game dfs 技巧
  4. 在navicat中查看所有表的注释
  5. 吴恩达 coursera ML 第十六课总结+作业答案
  6. 机器学习实战-聚类分析KMEANS算法-25
  7. POJ1390 Blocks——动态规划——pku1390
  8. 第三届蓝桥杯决赛真题---数量周期
  9. 【Rayeager PX2分享】OpenCV入门之图像显示
  10. particle filtering---粒子滤波(讲的很通俗易懂)
  11. Linux x86-64 IOMMU详解(六)——Intel IOMMU参与下的DMA Coherent Mapping流程
  12. OFD转PDF格式免费在线转换
  13. R语言rank函数详细解析
  14. html如何固定字号,css怎么控制字体大小?
  15. 虚拟机+服务器管理器怎么打开,大话西游2特色版虚拟机镜像一键服务端+启动教程+物品ID+GM设置方法+数据库工具等...
  16. 论文封面摘要正文页码不同 WORD中怎么编辑页码不连续 设置目录和正文页码不同
  17. python爬虫--scrapy框架的学习和使用(七)⭐---第二部分
  18. 未来 3 年,什么样的技术人,最有机会年赚 100万?
  19. JavaScript 函数 Call的使用
  20. asp mysql查询_asp的 条件查询

热门文章

  1. 部署LAMP论坛平台(Linux,Apache,MySQL,PHP)
  2. 对爬虫爬取到的数据进行存储
  3. OpenStack(三)——Glance组件
  4. mysql 云主机名_mysql部署到云主机的笔记
  5. lr分析器的设计与实现实验报告_《计算机导论》课程实验报告(一维数组)
  6. 以array开头的php函数,PHP 常用数组函数详解
  7. envi中的sg滤波_ENVI滤波
  8. 文件自定义变量_awk 内置变量与自定义变量
  9. android webview 截图,Android获取webView快照与屏幕截屏的方法 -电脑资料
  10. 12位18Bb20计算公式c语言,C语言的一些简单题目,没有答案,哪位大神帮忙做一下!!!...