Node-JS专精06手写EventHub

EventHub

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//订阅的事件
var eventMap = {
// 蒙牛:['张三','李四','王五'],
// 光明:['熊大','光头强']
};
var eventHub = {
trigger(eventName,data){
let fnList = eventMap[eventName];
if(!fnList) return
for(var i=0;i<fnList.length;i++){
fnList[i](data)
}
},
on(eventName,fn){
if(!eventMap[eventName]){
eventMap[eventName] = []
}
eventMap[eventName].push(fn)
}
}

// 订阅——事件
eventHub.on('我要用钱',function fn1(data){
console.log(data)
})

// 发布——事件
eventHub.trigger('我要用钱',100)

确定API

  • on
  • off
  • emit
  • 如果可能还有 once

环境配置先确保你有ts-node环境

1
2
3
yarn global add ts-node@8.3.0
ts-node -v
# 如果是 8.3.0 代表我们环境一致了

新建 index.ts

1
2
const a = 1;
console.log(a);

你就可以运行 ts代码了

1
ts-node index.ts

TS版 EventHub

001-JS版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class EventHub {
cache = {};
on(eventName,fn){
if(this.cache[eventName]=== undefined){
this.cache[eventName] = []
}
const array = this.cache[eventName];
array.push(fn)
}
emit(eventName){
let array = this.cache[eventName];
if(array === undefined){
array = [];
}
array.forEach(fn => fn());
}
}

002-JS优化版,支持传递data

1
2
3
4
5
6
7
8
9
10
class EventHub {
cache = {};
on(eventName,fn){
this.cache[eventName] = this.cache[eventName] || [];
this.cache[eventName].push(fn);
}
emit(eventName,data?){
(this.cache[eventName] || []).forEach(fn => fn(data));
}
}

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const eventHub  = new EventHub();
// eventHub 是个对象
console.assert(eventHub instanceof Object === true,"eventHub 是个对象");

// emit('xxx') 能被触发
let called = false;
eventHub.on('xxx',()=>{
called = true;
console.log("called:" + called);
})
eventHub.emit('xxx');


// 可以传递 abc
eventHub.on('xxx2',(y)=>{
console.assert(y === 'abc' === true,"传递emit('xxx2','abc')")
})
eventHub.emit('xxx2','abc');

003-JS-可以off

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class EventHub {
private cache = {};
on(eventName, fn){
this.cache[eventName] = this.cache[eventName] || [];
this.cache[eventName].push(fn);
}
emit(eventName, data?){
(this.cache[eventName] || []).forEach(fn => fn(data));
}
off(eventName, fn) {
let index = indexOf(this.cache[eventName], fn);
if (index === -1) return;
this.cache[eventName].splice(index, 1);
}
}

export default EventHub;

/**
* 帮助函数 indexOf
* @param array
* @param item
*/
function indexOf(array, item) {
if (array === undefined) return -1;

let index = -1;
for (let i = 0; i < array.length; i++) {
if (array[i] === item) {
index = i;
break;
}
}
return index;
}

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
{
const eventHub = new EventHub();
let called = false;
const fn1 = (y)=>{
called = true;
};
eventHub.on('xxx',fn1)
eventHub.off('xxx',fn1);
eventHub.emit('xxx','aaa');
setTimeout(()=>{
console.log(called);
},1000)
}

004-JS-完善测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import EventHub from "../src/index";

const test1 = message => {
const eventHub = new EventHub();
console.assert(eventHub instanceof Object === true,"eventHub 是个对象");
console.log(message);
}

const test2 = message => {
const eventHub = new EventHub();
let called = false;
eventHub.on('xxx',(y)=>{
called = true;

console.assert(y === 'abc' === true,"传递emit('xxx','abc')")
})
eventHub.emit('xxx','abc');
console.assert(called);
console.log(message);
}


const test3 = message => {
const eventHub = new EventHub();
let called = false;
const fn1 = (y)=>{
called = true;
};
eventHub.on('yyy',fn1)
eventHub.off('yyy',fn1);
eventHub.emit('yyy');
console.assert(called === false);
console.log(message);
}


test1("EventHub 可以创建对象");
test2(".on 了之后 .emit,会触发 .on 的函数");
test3(".off 有用");

一些疑问

  • emit('xxx',data) 能不能传递两个数据?
    • 面试容易问,你这个只能传一个参数,我想要两个怎么办?
    • 传一个数组不就好了
    • 这个没有规范的。面试技巧就是留一个坑给Ta踩
      1
      2
      3
      4
      5
      6
      7
      8
      9
      const eventHub = new EventHub();
      let called = false;
      eventHub.on("xxx", y => {
      called = true;
      console.assert(y[0] === "今天林志玲结婚了");
      console.assert(y[1] === "言承旭无话可说");
      });
      eventHub.emit("xxx", ["今天林志玲结婚了", "言承旭无话可说"]);
      console.assert(called);

代码仓库