1. 回调地狱的出现形式
举个栗子:
早上,我去早餐店吃早餐,按照习惯叫了豆浆和油条,因为豆浆是早就做好的,而油条是现炸的, 我不可能马上就能吃到,假设豆浆在1s后拿到,油条2s之后拿到,但是吃的时候我都习惯先吃一口油条,再喝一口豆浆,那么就有了以下:
function SoyaBeanMilk(fn){
setTimeout(()=>{
fn('豆浆')
},1000)
}
function friedBreadStick(fn){
setTimeout(()=>{
fn('油条')
},2000)
}
friedBreadStick(function(data){
console.log(data);
SoyaBeanMilk(function(data){
console.log(data);
})
})
输出结果:先2s拿到油条,再1s拿到豆浆
2. 回调地狱现象
当吃完油条,喝完豆浆,我依旧没有吃饱,在吃点别的呢,渐渐地就产生了回调地狱现象
在跟老板要两个包子,再来几个烧麦,就产生了如下:
friedBreadStick(function(data){
console.log(data);
SoyaBeanMilk(function(data){
console.log(data);
XXX(function(data){
console.log(data);
XXX(function(data){
console.log(data);
XXX(function(data){
console.log(data);
})
})
})
})
})
这一坨代码看得人细思极恐,像便便一样,不方便维护,
于是,es6引出了promise对象
3. promise对象
promise的详细用法请看===> js中的promise对象
promise中通过resolve参数将异步的数据传出去,再通过then获取
接下来对上面代码进行改造
function SoyaBeanMilk(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve('豆浆')
},1000)
})
}
function friedBreadStick(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve('油条')
},2000)
})
}
friedBreadStick().then(function(data){
console.log(data);
return SoyaBeanMilk()
}).then(function(data){
console.log(data);
})
结果依旧还是如此:
使用了promise的链式写法,这样代码稍微简洁了些,但是还是有些不好维护
于是,再次使用async,await
4. async await
await后面加一个promise对象就直接可以拿到resolve返回的值,并且可以赋值
await会等待后面的异步程序执行完毕之后再去执行下面的代码,所以看起来跟同步代码一样
async function getBreakfast(){
let friedBreadStick = await friedBreadStick();
console.log(friedBreadStick);
let SoyaBeanMilk = await SoyaBeanMilk();
console.log(SoyaBeanMilk);
}
优点:(更像是同步代码)结构清晰,方便维护,解决回调地狱