实现Event
# 实现Event
/**
* 考察设计模式 => 发布订阅模式. 实现 Event 类, 支持 once, on, off, emit
*/
class Event {
listeners = {};
on(type, fn) {
if (this.listeners[type]) {
this.listeners[type].push(fn);
} else {
this.listeners[type] = [fn];
}
}
emit(type, ...args) {
this.listeners[type].forEach((fn) => {
fn.apply(this, args);
});
}
off(type, fn) {
const index = this.listeners[type].indexOf(fn);
this.listeners[type].splice(index, 1);
}
once(type, fn) {
const cb = (...args) => {
fn.apply(this, args);
this.off(type, fn);
};
this.on(type, cb)
}
}
const event = new Event();
event.on('say', console.log);
event.once('eat', console.log);
event.emit('say', 'good bye')
event.emit('eat', 'dog', 'cat');
event.emit('eat', 'cat', 'flish');
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
40
41
42
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
40
41
42
// 单对象写法 Event 就相当于事件中心
const Event = function () {
// 使用闭包的好处:把EventPool私有化,外界无法访问EventPool
const EventPool = new Map();
// 使用 es6 map 来存储 event.callback 键值对
const isFunction = func => typeof func === 'function';
const on = (event, callback) => {
// 注册事件
EventPool.get(event) || EventPool.set(event, []);
if (isFunction(callback)) {
EventPool.get(event).push(callback);
}
else {
throw new Error('callback not is function')
}
};
const addEventListener = (event, callback) => {
// on 方法别名
on(event, callback);
};
const emit = (event, ...args) => {
// 触发(发布)事件
// 让事件的触发为一个异步的过程,即排在同步代码后执行
// 也可以 setTimeout(fn, 0)
Promise.resolve().then(() => {
let funcs = EventPool.get(event);
if (funcs) {
funcs.forEach(f => f(...args));
} else {
throw new Error(`${event} not register`)
}
})
};
const send = (event, ...args) => {
// emit 方法别名
emit(event, ...args)
};
const removeListener = event => {
// 删除事件
Promise.resolve(() => {
// 删除事件也为异步的过程
if (event) {
EventPool.delete(event);
} else {
throw new Error(`${event} not register`)
}
})
};
return {
on, emit, addEventListener, send
}
}();
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class EventEmiter {
constructor() {
this._EventPool = new Map();
}
on(event, callback) {
this._EventPool.get(event) || this._EventPool.set(event, []);
if(typeof callback === 'function') {
this._EventPool.get(event).push(callback);
}
else {
throw new Error('callback not is function')
}
}
addEventListener(event, callback) {
this.on(event, callback)
}
emit(event, ...args) {
Promise.resolve().then(() => {
let funcs = this._EventPool.get(event);
if (funcs) {
funcs.forEach(f => f(...args))
} else {
throw new Error(`${event} not register`)
}
})
}
send(event, ...args) {
this.emit(event, ...args)
}
removeListener(event) {
Promise.resolve().then(() => {
if (event) {
this._EventPool.delete(event)
} else {
throw new Error(`${event} not register`)
}
})
}
}
// (module) && (module.exports) && (module.exports = {Event, EventEmiter})
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
40
41
42
43
44
45
46
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
40
41
42
43
44
45
46