浅谈async/await
ES7的async/await语法在2016年就已经提出来了,惭愧的是我最近才接触使用,,下面来聊聊
解决了什么问题
在async/await之前,我们有三种方式写异步代码
-
嵌套回调
-
以Promise为主的链式回调
-
使用Generators
但是,这三种写起来都不够优雅,ES7做了优化改进,async/await应运而生,async/await相比较Promise 对象then 函数的嵌套,与 Generator 执行的繁琐(需要借助co才能自动执行,否则得手动调用next() ), Async/Await 可以让你轻松写出同步风格的代码同时又拥有异步机制,更加简洁,逻辑更加清晰。
async/await特点
-
async/await更加语义化,async 是“异步”的简写,async function 用于申明一个 function 是异步的; await,可以认为是async wait的简写, 用于等待一个异步方法执行完成;
-
async/await是一个用同步思维解决异步问题的方案(等结果出来之后,代码才会继续往下执行)
-
可以通过多层 async function 的同步写法代替传统的callback嵌套
async function语法
-
自动将常规函数转换成Promise,返回值也是一个Promise对象
-
只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数
-
异步函数内部可以使用await
async function name([param[, param[, ... param]]]) { statements } name: 函数名称。 param: 要传递给函数的参数的名称 statements: 函数体语句。 返回值: 返回的Promise对象会以async function的返回值进行解析,或者以该函数抛出的异常进行回绝。
await语法
-
await 放置在Promise调用之前,await 强制后面点代码等待,直到Promise对象resolve,得到resolve的值作为await表达式的运算结果
-
await只能在async函数内部使用,用在普通函数里就会报错
[return_value] = await expression; expression: 一个 Promise 对象或者任何要等待的值。 返回值:返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。
错误处理
在async函数里,无论是Promise reject的数据还是逻辑报错,都会被默默吞掉,所以最好把await放入try{}catch{}中,catch能够捕捉到Promise对象rejected的数据或者抛出的异常
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => {reject('error')}, ms); //reject模拟出错,返回error }); } async function asyncPrint(ms) { try { console.log('start'); await timeout(ms); //这里返回了错误 console.log('end'); //所以这句代码不会被执行了 } catch(err) { console.log(err); //这里捕捉到错误error } } asyncPrint(1000);
如果不用try/catch的话,也可以像下面这样处理错误(因为async函数执行后返回一个promise)
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => {reject('error')}, ms); //reject模拟出错,返回error }); } async function asyncPrint(ms) { console.log('start'); await timeout(ms) console.log('end'); //这句代码不会被执行了 } asyncPrint(1000).catch(err => { console.log(err); // 从这里捕捉到错误 });
如果你不想让错误中断后面代码的执行,可以提前截留住错误,像下面
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => { reject('error') }, ms); //reject模拟出错,返回error }); } async function asyncPrint(ms) { console.log('start'); await timeout(ms).catch(err => { // 注意要用catch console.log(err) }) console.log('end'); //这句代码会被执行 } asyncPrint(1000);
使用场景
多个await命令的异步操作,如果不存在依赖关系(后面的await不依赖前一个await返回的结果),用Promise.all()让它们同时触发
function test1 () { return new Promise((resolve, reject) => { setTimeout(() => { resolve(1) }, 1000) }) } function test2 () { return new Promise((resolve, reject) => { setTimeout(() => { resolve(2) }, 2000) }) } async function exc1 () { console.log('exc1 start:',Date.now()) let res1 = await test1(); let res2 = await test2(); // 不依赖 res1 的值 console.log('exc1 end:', Date.now()) } async function exc2 () { console.log('exc2 start:',Date.now()) let [res1, res2] = await Promise.all([test1(), test2()]) console.log('exc2 end:', Date.now()) } exc1(); exc2();
exc1 的两个并列await的写法,比较耗时,只有test1执行完了才会执行test2
你可以在浏览器的Console里尝试一下,会发现exc2的用Promise.all执行更快一些

兼容性

在自己的项目中使用
通过 babel 来使用。
只需要设置 presets 为 stage-3 即可。
安装依赖:
npm install babel-preset-es2015 babel-preset-stage-3 babel-runtime babel-plugin-transform-runtime
修改.babelrc:
"presets": ["es2015", "stage-3"], "plugins": ["transform-runtime"]
作者:coder_Lucky
链接:https://www.jianshu.com/p/1e75bd387aa0
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2019-06-11 gradle上sourceSets配置&同名文件合并问题
2019-06-11 ssm中web配置各框架的配置文件路径方式
2019-06-11 MyBatis Spring整合配置映射接口类与映射xml文件
2019-06-11 gradle + mybatis 复制xml等配置文件到输出目录