解决异步函数
我们通常使用回调或者事件来解决异步问题。
事件
某个对象的属性是一个函数,当发生某一件事情时,调用函数。
//html代码:
<div>
<button id="btn1">按钮1:给按钮2注册点击事件</button>
<button id="btn2">按钮2:给按钮3注册点击事件</button>
<button id="btn3">按钮3:点击后弹出hello</button>
</div>
//js代码
const btn1 = document.getElementById("btn1"),
btn2 = document.getElementById("btn2"),
btn3 = document.getElementById("btn3");
btn1.addEventListener("click", function() {
btn2.addEventListener("click", function() {
btn3.addEventListener("click", function() {
alert("hello");
})
})
})
我们需要先点击按钮1,再点击按钮2,最后点击按钮3才会弹出hello,这样的代码结构非常的乱,也不利于阅读
回调
运行某个函数的时候,传一个函数作为参数,当发生某件事情时,会运行该函数
/*
小明心中有三个女神
有一天,小明决定向第一个女神表白,如果女神拒绝,则向第二个女神表白,
直到所有的女神都拒绝,或有一个女神同意为止
*/
function biaobai(god, callback) {
console.log(`小明向女神${god}发出了表白短信`);
setTimeout(() => {
if (Math.random() < 0.1) {
callback(true);
} else {
callback(false);
}
}, 1000);
}
biaobai("女神1", function(result) {
if (result) {
console.log("女神1答应了,小明很开心!")
} else {
console.log("女神1拒绝了,小明表示无压力,然后向女神2表白");
biaobai("女神2", function(result) {
if (result) {
console.log("女神2答应了,小明很开心!")
} else {
console.log("女神2十分感动,然后拒绝了小明,小明向女神3表白");
biaobai("女神3", function(result) {
if (result) {
console.log("女神3答应了,小明很开心!")
} else {
console.log("小明表示生无可恋!!");
}
})
}
})
}
})
这样的代码一点都不利于维护,我相信大多数人看到这样的代码估计都是两眼一黑,想直接给它删掉了好了。
怎么办
本质上,事件和回调没有区别,只是函数放置的位置不同。但是它面临下面两个问题:
- 回调地狱:某个异步操作需要等待之前的异步操作完成,无论用回调还是事件,都会陷入不断的嵌套
- 异步之间的联系:某个异步操作要等待多个异步操作的结果,对这种联系的处理,会让代码的复杂度剧增
解决这两个问题的方法是使用Promise