今天在学习koa2的时候发现自己对async的使用方法和原理都不是很熟悉,连带着发现自己对前端异步的解决方案并了解并不如何深刻,所以干脆把前端现有的异步解决方案都复习了一遍。
今天先把将用callback和事件监听思想解决异步问题的代码贴出来,明天再补充代码的解析及其他解决方案;
CallBack
function f1(f2) {
setTimeout(function () {
let b = 10;
f2(b)
}, 1000)
}
function f2(data) {
console.log("callback_type_demo", data)
}
f1(f2);
这么写之后会于1s后再控制台打出 callback_type_demo 10。该方式容易理解,实际上就是是在f1执行完之后再调用f2,但是这个方法在多个异步操作嵌套的时候就变得非常难受。比如说这样:
function f1(f) {
setTimeout(function () {
let a = 10;
setTimeout(function () {
let b = a + 10;
setTimeout(function () {
let c = b + 10;
setTimeout(function () {
let d = c + 10;
setTimeout(function () {
let e = d + 10;
f(e)
}, 1000)
}, 1000)
}, 1000)
}, 1000)
}, 1000)
}
function finalF(data){
console.log('finalF',data)
}
f1(finalF);
代码执行完之后会于5s后打印出 finalF 50,多层嵌套之后该方法的语义就会开始不清晰,不容易理解与维护,并且在实际情况中,我们还需要对借口返回的错误进行处理,那么这个写法就变得愈发的混乱和复杂,所以该方法是不可取的;
事件监听
以下是我对 可以被监听事件的对象DOM 的实现,不想了解具体实现方式的可以跳过
//实现事件监听
/*
DOM 可以被监听事件的对象
.on("eventName",function) 第一个参数为监听的事件名,第二个参数为 绑定 的方法
.removeOn("eventName",function) 第一个参数为监听的事件名,第二个参数为 解绑 的方法
.trigger("eventName") 参数接收事件名,触发该事件(并触发该事件绑定的所有方法)
*/
//具体实现可以不看,不影响对事件监听解决异步的理解
let DOM = function () {
//被监听的事件的集合
let eventList = {};
//绑定事件监听的方法
this.on = function (eventName, fun) {
if (typeof eventName !== "string") {
console.error("监听的事件名应为字符串");
return;
}
if (typeof fun !== "function") {
console.error("被触发的必须是事件");
return;
}
eventList[eventName] = eventList[eventName] || [];
eventList[eventName].push(fun);
};
//移除事件监听的方法
this.removeOn = function (eventName, fun) {
let onList = eventList[eventName];
if (onList) {
for (let i = 0; i < onList.length; i++) {
if (onList[i] === fun) {
onList.splice(i, 1);
return
}
}
}
};
//触发事件监听的方法
this.trigger = function (eventName, param) {
let onList = eventList[eventName];
if (onList) {
for (let i = 0; i < onList.length; i++) {
onList[i](param)
}
}
};
};
接下来的是利用事件监听解决异步的方案,需要认真看的
//生成两个DOM实例
let dom1 = new DOM();
let dom2 = new DOM();
//异步模拟
let f2 = function () {
setTimeout(function () {
console.log("开始触发事件:");
console.log("dom1 'done' 事件 触发:");
dom1.trigger('done', 20);
console.log("dom2 'done' 事件 触发:");
dom2.trigger("done", "123");
}, 100);
};
let f3 = function (data) {
console.log("f3 run",data)
};
//为dom1,dom2的'done' 事件绑定 f3 方法
console.log("dom1 On f3");
dom1.on("done", f3);
console.log("dom1 On f3");
dom2.on("done", f3);
f2();
setTimeout(function () {
console.log("dom1 removeOn f3");
dom1.removeOn("done", f3);
f2();
}, 200);
这里贴出该代码的运行日志
这里可以看到被绑定之后,第一次f2运行时,f3分别被dom1, dom2的'done'事件触发了;
但是在dom1解绑了f3之后,f2再次运行时,f3就只被dom2的‘done’事件触发了
事件监听模式不用关心被绑定的函数什么时候执行,我们只需要在特定的时候触发对应的事件就可以了。同时这个模式也程序相当的依赖事件,变成事件驱动,运行流程会变得很不清晰。
今天的文章就写到这里了,都是自己学习的经历和理解,希望大家多多斧正,多多关注,感谢