js async/await
一、async
带async关键字的函数,是声明异步函数,返回值是promise对象,如果async关键字函数返回的不是promise,会自动用Promise.resolve()包装。
async function test() {
return 'test'
}
test();
返回值为 Promise {<resolved>: "test"}。
二、await
await等待右侧表达式的结果,这个结果是promise对象或者其他值。
如果它等到的不是一个 promise 对象,那 await 表达式的运算结果就是它等到的东西。
如果它等到的是一个 promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。
function test() {
return new Promise(resolve => {
setTimeout(() => resolve("test"), );
});
}
const result = await test();
console.log(result);
console.log('end')
由于test()造成的阻塞,console.log('end')会等到两秒后执行
所以为了避免造成阻塞,await 必须用在 async 函数中,async 函数调用不会造成阻塞。
function test() {
return new Promise(resolve => {
setTimeout(() => resolve("test"), );
});
}
async function test2() {
const result = await test();
console.log(result);
}
test2();
console.log('end');
先执行console.log('end'),两秒后执行console.log('test')
如果await用在普通函数中,会报错,如下:

三、async/await的执行顺序
遇到await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,继续执行await后面的代码。以下面的代码分析:
async function test1() {
console.log('start test1');
console.log(await test2());
console.log('end test1');
}
async function test2() {
console.log('test2');
return await 'return test2 value'
}
test1();
console.log('start async');
setTimeout(() => {
console.log('setTimeout');
}, );
new Promise((resolve, reject) => {
console.log('promise1');
resolve();
}).then(() => {
console.log('promise2');
});
console.log('end async');
执行的结果

· 首先执行宏任务,执行test1函数,执行console.log('statr test1')
· 遇到await,先执行右边test2中的console.log('test2'),中断了后面的代码,执行test1外面的同步代码
· 执行console.log('start async');
· 遇到setTimeout,推到到下个宏任务队列中
· 执行Promise里面的同步代码console.log('promise1')
· 运行到promise().then,发现是promise对象,推到微任务队列中
· 执行console.log('end async')
· test1外面的同步代码执行结束后,回到test1中,console.log(await test2())执行完成后返回Promise {<resolved>: "return test2 value"},是promise对象,推到微任务队列中
· 此时第一个宏任务结束,执行所有的微任务,因为微任务队列先进先出,所以先执行console.log('promise2'),后执行console.log('return test2 value')
· 执行test2完成后,后面的代码不再阻塞,执行console.log('end test1');
· 执行下个宏任务,即执行console.log('setTimeout');
补充下有关宏任务和微任务的知识
宏任务和微任务都是队列,宏任务有script、setTimeout、setInterval等,微任务有Promise.then catch finally、process.nextTick等,宏任务和微任务的关系如下:

先执行第一个宏任务,执行结束后,执行所有的微任务,然后执行下个宏任务。
四、async/await的优缺点
1. 优点
相对于promise,async/await处理 then 的调用链,代码要清晰很多,几乎和同步代码一样
2. 缺点
滥用 await 可能会导致性能问题,因为 await 会阻塞代码
五、处理reject
1. try/catch
async function fn() {
try {
await new Promise((resolve, reject) => {
setTimeout(() => {
reject('err3');
}, );
})
} catch (err){
alert(err)
}
}
fn()
2. catch
async function fn() {
await new Promise((resolve, reject) => {
setTimeout(() => {
reject('err');
}, );
})
}
fn().catch(alert)
参考:
1. https://segmentfault.com/a/1190000007535316
2. https://segmentfault.com/a/1190000017224799
3. https://www.cnblogs.com/wangziye/p/9566454.html
js async/await的更多相关文章
- js async await 终极异步解决方案
既然有了promise 为什么还要有async await ? 当然是promise 也不是完美的异步解决方案,而 async await 的写法看起来更加简单且容易理解. 回顾 Promise Pr ...
- node.js async/await 继发执行与并发执行
async/await 继发执行与并发执行,看如何控制 两个异步函数 foo bar function foo() { return new Promise((resolve, reject) =&g ...
- [转] js async await 终极异步解决方案
阅读目录 回顾 Promise async await 字面理解 async.await 如何执行 await 操作符 总结 既然有了promise 为什么还要有async await ? 当然是pr ...
- [node.js] async/await如何优雅处理异常?
node.js的世界,从callback开始,不会止于async. 所有人都在骂为什么不能完全进化,其实我感觉这就是老外的细心,为了承上.这也就是为什么async其实就是promise一样,假如不是一 ...
- 图与例解读Async/Await
JavaScript ES7的async/await语法让异步promise操作起来更方便.如果你需要从多个数据库或者接口按顺序异步获取数据,你可能最终写出一坨纠缠不清的promise与回调.然而使用 ...
- js异步编程终级解决方案 async/await
在最新的ES7(ES2017)中提出的前端异步特性:async.await. async.await是什么 async顾名思义是“异步”的意思,async用于声明一个函数是异步的.而await从字 ...
- callback vs async.js vs promise vs async / await
需求: A.依次读取 A|B|C 三个文件,如果有失败,则立即终止. B.同时读取 A|B|C 三个文件,如果有失败,则立即终止. 一.callback 需求A: let read = functio ...
- 【学习笔记】JS经典异步操作,从闭包到async/await
参考文献:王仕军——知乎专栏前端周刊 感谢作者的热心总结,本文在理解的基础上,根据自己能力水平作了一点小小的修改,在加深自己印象的同时也希望能和各位共同进步... 1. 异步与for循环 抛出一个问题 ...
- JS异步编程 (2) - Promise、Generator、async/await
JS异步编程 (2) - Promise.Generator.async/await 上篇文章我们讲了下JS异步编程的相关知识,比如什么是异步,为什么要使用异步编程以及在浏览器中JS如何实现异步的.最 ...
随机推荐
- unity3D编辑器扩展
编辑器扩展只是在编辑项目中运行,发布出来是不会运行的. 固定创建一个文件夹Editor:所有的资源或者代码都不会被打包进去. 01.使用MenuItem添加菜单栏按钮 脚本不需要作为组件存在,可以不用 ...
- Delphi中那些容易混淆的基础
@.^.Addr.Pointer Delphi(Pascal)中有几个特殊的符号,如@.^等,弄清楚这些符号的运行,首先要明白Delphi指针的一些基础知识:指针,是一个无符号整数(unsigned ...
- Python基础-读取excel
import xlrdbook = xlrd.open_workbook('lanxia.xls')sheet = book.sheet_by_name('sheet1')rows = sheet.n ...
- BEC listen and translation exercise 48
It's not publicly known who the kidnappers were. Because they are not eating such lovely food since ...
- (转)Java 调用 C++ (Java 调用 dll)
转自: http://www.cnblogs.com/baokang/p/4979243.html 因为要做点图形处理的项目,需要在Java中调用dll库,所以开发的第一步是研究了一下Java Jni ...
- Android中高效的显示图片之三——缓存图片
加载一张图片到UI相对比较简单,如果一次要加载一组图片,就会变得麻烦很多.像ListView,GridView,ViewPager等控件,需要显示的图片和将要显示的图片数量可能会很大. 为了减少内存使 ...
- pandas 学习 —— pivot table
0. DataFrame 的 index.columns.values >> df = pd.DataFrame(np.arange(6).reshape(3, 2), index=['o ...
- Spring MVC表单提交
实际应用中,列表中的单条记录的修改,可能需要传很多对象参数到后台服务器,Spring MVC表单标签<form:> 提供了一种简洁的提交方式. <form id="form ...
- 20179215《Linux内核原理与分析》第一周作业
一.Linux介绍 我们现在很常见Windows系统,对于Linux则显得尤为陌生.当然我也不例外,初识Linux过程中遇到一些困惑,但我也在实验的同时通过不断查找资料与实践中慢慢解决问题.那么下面我 ...
- Java Modifiers
Private means this could only be seen within this class. Protected means "package private" ...