事件和回调函数的缺陷
我们习惯于使用传统的回调或事件处理来解决异步问题
事件:某个对象的属性是一个函数,当发生某一件事时,运行该函数
dom.onclick = function(){
}
回调:运行某个函数以实现某个功能的时候,传入一个函数作为参数,当发生某件事的时候,会运行该函数。
dom.addEventListener("click", function(){
})
本质上,事件和回调并没有本质的区别,只是把函数放置的位置不同而已。
一直以来,该模式都运作良好。
直到前端工程越来越复杂…
目前,该模式主要面临以下两个问题:
回调地狱:某个异步操作需要等待之前的异步操作完成,无论用回调还是事件,都会陷入不断的嵌套
实例1
<div>
<button id="btn1">按钮1:给按钮2注册点击事件</button>
<button id="btn2">按钮2:给按钮3注册点击事件</button>
<button id="btn3">按钮3:点击后弹出hello</button>
</div>
const btn1 = document.querySelector("#btn1"),
btn2 = document.querySelector("#btn2"),
btn3 = document.querySelector("#btn3");
btn1.addEventListener("click",()=>{
btn2.addEventListener('click',()=>{
btn3.addEventListener('click',()=>{
alert("hello")
})
})
})
实例2
/*
邓哥心中有三个女神
有一天,邓哥决定向第一个女神表白,如果女神拒绝,则向第二个女神表白,直到所有的女神都拒绝,或有一个女神同意为止
用代码模拟上面的场景
*/
function biaobai(god, callback) {
console.log(`邓哥向女神【${god}】发出了表白短信`);
setTimeout(() => {
if (Math.random() < 0.1) {
//女神同意拉
//resolve
callback(true);
} else {
//resolve
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("邓哥表示生无可恋!!");
}
})
}
})
}
})
实例3 (json可自行编写)
//获取李华所在班级的老师的信息
ajax({
url: "./data/students.json?name=李华",
success: function(data) {
for (let i = 0; i < data.length; i++) {
if (data[i].name === "李华") {
const cid = data[i].classId;
ajax({
url: "./data/classes.json?id=" + cid,
success: function(data) {
for (let i = 0; i < data.length; i++) {
if (data[i].id === cid) {
const tid = data[i].teacherId;
ajax({
url: "./data/teachers.json?id=" + tid,
success: function(data) {
for (let i = 0; i < data.length; i++) {
if (data[i].id === tid) {
console.log(data[i]);
}
}
}
})
return;
}
}
}
})
return;
}
}
}
})
- 异步之间的联系:某个异步操作要等待多个异步操作的结果,对这种联系的处理,会让代码的复杂度剧增