一、事件和回调
我们习惯于使用传统的回调或事件处理来解决异步问题
1.事件
某个对象的属性是一个函数,当发生某一件事时,运行该函数
dom.onclick = function(){
}
2.回调
运行某个函数以实现某个功能的时候,传入一个函数作为参数,当发生某件事的时候,会运行该函数。
dom.addEventListener("click", function(){
});
本质上,事件和回调并没有本质的区别,只是把函数放置的位置不同而已。事件上为属性,回调上为参数。
二、问题与缺陷
1.回调地狱
某个异步操作需要等待之前的异步操作完成,无论用回调还是事件,都会陷入不断的嵌套
const btn1 = document.getElementById("btn1"),
btn2 = document.getElementById("btn2"),
btn3 = document.getElementById("btn3");
btn1.addEventListener("click", function() {
//按钮1的其他事情
btn2.addEventListener("click", function() {
//按钮2的其他事情
btn3.addEventListener("click", function() {
alert("hello");
})
})
})
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("表示生无可恋!!");
}
});
}
});
}
});
这里还只是三步,如果实际中需要更多,将使代码效率变得低下。
2. 异步之间的联系:
某个异步操作要等待多个异步操作的结果,对这种联系的处理,会让代码的复杂度剧增
//通过请求到的数据筛选其它请求到的数据
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;
}
}
}
});