async/await是基于promises的语法糖。可以说是对 Promise的有益补充。
1.async/await
快速掌握async/await的用法,你只需要理解以下几点:
什么是地狱回调呢?
接着我们上一节的Promise案例,这里就会产生经典的回调地狱。
function eat() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('吃饭...')
resolve('success')
}, 5000);
})
}
function drink() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('喝茶...')
resolve('success')
}, 1000);
})
}
function bath(){
return new Promise((reslove, reject) => {
setTimeout(() => {
console.log('洗澡...')
reslove('success')
}, 3000);
})
}
let cooking = (flag) => {
return new Promise((reslove, reject) => {
setTimeout(() => {
if (flag) {
reslove('success')
}
reject('fail')
}, 5000);
console.log('做饭无聊时,拍个抖音.....')
})
}
console.log('准备开始做饭了....')
let p = cooking(true);
p.then(resp => {
console.log(resp)
if (resp === 'success') {
eat().then(resp => {
if(resp === 'success'){
drink().then(resp=>{
if(resp === 'success'){
bath().then(resp=>{
})
}
})
}
})
}
}).catch(err => {
console.log(err)
})
console.log('做饭的同时干些其它事情....')
运行结果:
准备开始做饭了....
做饭无聊时,拍个抖音.....
做饭的同时干些其它事情....
success
吃饭...
喝茶...
洗澡...
这种多层回调函数的相互嵌套,就形成了回调地狱现象。async/await的出现就完美的解决了回调地狱问题。
以下有小伙伴的实现方式:
let cooking = (flag) => {
return new Promise((reslove, reject) => {
setTimeout(() => {
if (flag) {
reslove('success')
}
reject('fail')
}, 5000);
console.log('做饭无聊时,拍个抖音.....')
})
}
async function eat() {
setTimeout(() => {
console.log('吃饭...')
}, 5000);
return 'success';
}
async function drink() {
setTimeout(() => {
console.log('喝茶...')
}, 2000)
return 'success';
}
async function bath() {
setTimeout(() => {
console.log('洗澡...')
}, 3000)
return 'success'
}
console.log('准备开始做饭了....')
async function haveGoodTime() {
await cooking(true);
await eat();
await drink();
await bath();
}
console.log('做饭的同时干些其它事情....')
haveGoodTime();
运行结果:
准备开始做饭了....
做饭的同时干些其它事情....
做饭无聊时,拍个抖音.....
喝茶...
洗澡...
吃饭...
我们发现又出现了先喝茶,洗澡,再吃饭的尴尬次序。错误的原因在于await后面并不是Promise对象。因此无法保证线程同步。
let cooking = (flag) => {
return new Promise((reslove, reject) => {
setTimeout(() => {
if (flag) {
reslove('success')
}
reject('fail')
}, 5000);
console.log('做饭无聊时,拍个抖音.....')
})
}
async function eat() {
return new Promise((reslove,reject)=>{
setTimeout(() => {
console.log('吃饭...')
reslove('success')
}, 5000);
})
}
async function drink() {
return new Promise((reslove,reject)=>{
setTimeout(() => {
console.log('喝茶...')
reslove('success')
}, 2000);
})
}
async function bath(time) {
return new Promise((reslove,reject)=>{
setTimeout(() => {
console.log('洗澡...')
reslove('success')
}, 3000);
})
}
console.log('准备开始做饭了....')
async function haveGoodTime() {
await cooking(true);
await eat();
await drink();
await bath();
}
console.log('做饭的同时干些其它事情....')
haveGoodTime();
运行结果:
准备开始做饭了....
做饭的同时干些其它事情....
做饭无聊时,拍个抖音.....
吃饭...
喝茶...
洗澡...
执行次序完全正确,而且使得异步代码的执行看起来像同步代码的写法。
我们进一步优化,把每次生成Promise的过程封装成一个方法,大大提高了代码的复用性。
async function takeLongTime(value,time) {
return new Promise((resolve,reject) => {
console.log(value);
setTimeout(() => resolve('success'), time);
});
}
let cooking = (flag) => {
return new Promise((reslove, reject) => {
setTimeout(() => {
if (flag) {
reslove('success')
}
reject('fail')
}, 5000);
console.log('做饭无聊时,拍个抖音.....')
})
}
async function eat(time) {
return takeLongTime('吃饭...',5000);
}
async function drink(time) {
return takeLongTime('喝茶...',2000);
}
async function bath(time) {
return takeLongTime('洗澡...',3000);
}
console.log('准备开始做饭了....')
async function haveGoodTime() {
await cooking(true);
await eat();
await drink();
await bath();
}
console.log('做饭的同时干些其它事情....')
haveGoodTime();
执行次序完全相同。同理,如果在吃饭时发生意外,那么也无法继续喝茶和洗澡。但是要记得捕获异常呦!
async function takeLongTime(value,time) {
return new Promise((resolve,reject) => {
console.log(value);
if(value === '吃饭...') {
reject('吃饭噎住了...')
}
setTimeout(() => resolve('success'), time);
});
}
let cooking = (flag) => {
return new Promise((reslove, reject) => {
setTimeout(() => {
if (flag) {
reslove('success')
}
reject('fail')
}, 5000);
console.log('做饭无聊时,拍个抖音.....')
})
}
async function eat(time) {
return takeLongTime('吃饭...',5000);
}
async function drink(time) {
return takeLongTime('喝茶...',2000);
}
async function bath(time) {
return takeLongTime('洗澡...',3000);
}
console.log('准备开始做饭了....')
async function haveGoodTime() {
try {
await cooking(true);
await eat();
await drink();
await bath();
}catch(err){
console.log(err)
}
}
console.log('做饭的同时干些其它事情....')
haveGoodTime();
运行结果:
准备开始做饭了....
做饭的同时干些其它事情....
做饭无聊时,拍个抖音.....
吃饭...
吃饭噎住了...
2.小结