2

今天在学习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’事件触发了
事件监听模式不用关心被绑定的函数什么时候执行,我们只需要在特定的时候触发对应的事件就可以了。同时这个模式也程序相当的依赖事件,变成事件驱动,运行流程会变得很不清晰。


今天的文章就写到这里了,都是自己学习的经历和理解,希望大家多多斧正,多多关注,感谢


胡晓峰
97 声望2 粉丝

撼大摧坚,徐徐图之