通过这一章的学习,我们已经了解了Promise是如何解决异步回调地狱问题的,接下来我们来 扩展一个新的知识——async和await
一、什么是async/await?
async/await 是基于Promise实现的。
async/await 使得异步代码看起来像同步代码。
以前的方法有回调函数和Promise, async/await是写异步代码的新方法。
二、async/await语法
async函数返回一个Promise对象,可以使用then 方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到触发的异步操作完成,再接着执行函数体后面的语句。示例:
const timeout= time => {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
}, time);
})
};
const start = async () => {
// 在这里使用起来就像同步代码那样直观
console.log('start');
await timeout(3000);
console.log('end');
return "imooc"
};
start().then(()=> {
console.log('test....')
});
执行上面的代码,控制台先输出start,稍等3秒后,输出了end,接着输出test...。如下图所示:
三、注意事项:
1.await命令只能用在async函数之中,如果用在普通函数,就会报错。示例:
const timeout = time => {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
}, time);
})
};
function fn() {
await timeout(300)
}
fn()
执行上面的代码,由于在普通函数fn中使用了await,控制台出现报错,如下图所示:
将fn改为async函数就不会报错,示例:
const timeout = time => {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
}, time);
})
};
async function fn() {
await timeout(300)
}
fn()
2.await后面跟着是一个Promise对象,会等待Promise返回结果了,再继续执行后面的代码。示例:
const timeout = time => {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log('imooc')
resolve();
}, time);
})
};
const start = async () => {
await timeout(3000);
console.log('end');
};
start()
执行上面的代码,控制台等待3秒后,输出imooc,然后才输出后面的console.log语句中的end,如下图所示:
3.await后面跟着的是一个数值或者是字符串等数据类型的值,则直接返回该值:
const num = 1
const str = "imooc"
const arr = [1,2]
const start = async () => {
console.log(await num)
console.log(await str)
console.log(await arr)
};
start()
4.await后面跟着的是定时器,不会等待定时器里面的代码执行完,而是直接执行后面的代码,然后再执行定时器中的代码。示例:
const start = async () => {
console.log(1)
await setTimeout(() => {
console.log(2)
}, 1000);
console.log(3);
};
start()
执行上面的代码,控制台一次输出1,3,隔一秒后输出2.如下图所示:
四、错误捕获
可以直接用标准的try catch语法捕捉错误,示例:
const timeout = time => {
return new Promise(function (resolve, reject) {
setTimeout(function () {
// 模拟出错了,返回 ‘error’
reject('error');
}, time);
})
};
const start = async () =>{
try {
console.log('start');
await timeout(3000); // 这里得到了一个返回错误
// 所以以下代码不会被执行了
console.log('end');
} catch (err) {
console.log(err); // 这里捕捉到错误 `error`
}
};
start()
执行上面的代码,控制台先输出start,await等待调用timeout方法返回的Promise对象返回了一个错误,那么后面的代码就不会执行了,直接进入catch,捕捉到错误,在控制台输出error。如下图所示:
五、总结
async/await方式虽然使得异步操作变得更加方便和易读,但它还是基于Promise的,不必太过纠结到底使用哪种方式,具体情况具体分析,能解决问题的技术就是好技术。