以前的应用主要是可视化,在异步请求数据部分一直是写一个ajax,然后在回调函数里处理返回的数据,这样做虽然简单,但是在代码的可读性和可维护性上相当糟糕,因此有必要采用新的异步调用方法,更优雅地实现请求过程。
1.async/await简介
async/await更加语义化,async 是“异步”的简写,async function 用于申明一个 function 是异步的; await,可以认为是async wait的简写, 用于等待一个异步方法执行完成;
async/await是一个用同步思维解决异步问题的方案(等结果出来之后,代码才会继续往下执行),其本身是一个语法糖,原理是通过结合promise和generator实现的,写法简洁高效。
2.async/await语法
async function funcname([param[, param[, ... param]]]) {
let data = await getDataBack();
//using data do something
}
async声明的函数
- return值是一个Promise对象;
- async函数内部可以使用await。
await语句
- await将强制后面点代码等待,直到Promise对象resolve,得到resolve的值作为await表达式的运算结果;
- await只能在async函数中使用。
3.多个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(); // 如果res2 依赖 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();
4.错误处理
在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);
或者也可以写在执行函数的后面:
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); // 从这里捕捉到错误
});