公司的前端工程使用了ES6语法,最近看代码的时候还是有很多疑惑的,本文主要记录一下async/await相关知识
1. async
使用谷歌浏览器开发者工具写脚本进行测试
- 按F12打开开发者工具
- 点击
Source
- 在左侧选择
Snippets
,点击New snippets创建一个新文件
- 输入以下代码
async function add(x) { let a = 1; return x + a; } add(10);
- 运行此脚本,在控制台可以看到有结果输出
- 返回的结果是一个Promise对象,状态是
fulfilled
,值是11
2. await
- await 放置在Promise调用之前,强制后面的代码等待,直到Promise对象resolve,得到resolve的值作为await表达式的运算结果
- await只能在async函数内部使用,用在普通函数里会报错
-
新建一个脚本文件,输入以下代码:
function test_promise() { return new Promise(function(resolve, reject) { resolve('resolve result') }); } async function run_test() { let a = await test_promise() let b = await ' and a simple string' console.log(a) console.log(b) return a + b } run_test();
运行结果为:
-
给test_promise方法添加延时,修改test_promise()方法
function test_promise() { return new Promise(function(resolve, reject) { setTimeout(() => { resolve('resolve result') }, 3000) }); }
运行结果为:
注意,PromiseResult的值即为run_test()
方法的返回值
3. 错误处理
-
未捕获错误
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => {reject('error')}, ms); }); } async function asyncPrint(ms) { console.log('start'); await timeout(ms); //这里返回了错误 console.log('end'); //所以这句代码不会被执行了 } asyncPrint(1000);
运行结果:
本例中我们并没有捕获错误,控制台打印 Uncaught error
-
捕获错误
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => {reject('error')}, ms); //reject模拟出错,返回error }); } // 使用 try catch 捕获异常,包括promise对象reject的数据或者抛出的异常 async function asyncPrint(ms) { try { console.log('start'); await timeout(ms); console.log('end'); } catch(err) { console.log(err); } } asyncPrint(1000);
或者使用如下方式
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) });
运行结果:
首先打印了start,然后在执行timeout
函数时,调用reject
回调。错误被捕获,打印出"error"。
-
如果想在出现异常后仍然执行后续代码,示例代码如下:
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => { reject('error') }, ms); }); } async function asyncPrint(ms) { console.log('start'); await timeout(ms).catch(err => { console.log(err) }) console.log('end'); } asyncPrint(1000);
运行结果:
4. Promise.all()
多个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();
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函数耗时约为3秒,而执行exc2函数耗时约为2秒。表明在exc2函数中, 使用Promise.all同时触发了test1和test2这2个异步函数。
参考: