实现一个 Message
类,里面包含 on
和 dispatch
方法,实现消息的发布订阅
Message 类的实现如下
class Message {
constructor() {
this.registered = {}; // 注册的事件
this.executing = {}; // 注册前先发布的消息,等注册的时候先把这里的执行一遍
}
// 订阅
on(method, fn) {
if (method in this.registered) {
this.registered[method].push(fn);
} else {
this.registered[method] = [fn];
}
setImmediate(() => { // 以下代码会在下一个事件循环中执行,目的是为了等所有事件注册完毕
if (method in this.executing) {
this.executing[method].forEach(data => this.dispatch(method, data));
delete this.executing[method];
}
});
}
// 发布
dispatch(method, data) {
if (method in this.registered) {
this.registered[method].forEach(fn => fn(data));
} else {
if (method in this.executing) {
this.executing[method].push(data);
} else {
this.executing[method] = [data];
}
}
}
}
功能测试
// 创建一个 `Message` 实例
const message = new Message();
// 先发布一个没注册过的 `hover` 事件
message.dispatch('hover', {message: '绑定事件前就发布的'});
// 注册一个 `click` 事件
message.on('click', data => {
console.log(`点击1,消息:${data.message}`);
});
// 注册一个 `hover` 事件
message.on('hover', data => {
console.log(`划过1,消息:${data.message}`);
});
// 又注册一个 `hover` 事件,之后发布 `hover` 消息的时候会按注册顺序依次执行
message.on('hover', data => {
console.log(`划过2,消息:${data.message}`);
});
// 又注册一个 `click` 事件
message.on('click', data => {
console.log(`点击2,消息:${data.message}`);
});
// 模拟一秒后发布了 `click` 事件
setTimeout(() => {
message.dispatch('click', {message: '点击的消息'});
}, 1000);
// 模拟两秒后发布了 `hover` 事件
setTimeout(() => {
message.dispatch('hover', {message: '绑定事件后发布的'});
}, 2000);
执行结果:
划过1,消息:绑定事件前就发布的
划过2,消息:绑定事件前就发布的
点击1,消息:点击的消息
点击2,消息:点击的消息
划过1,消息:绑定事件后发布的
划过2,消息:绑定事件后发布的
其中,第一行和第二行立即显示;第三行和第四行在一秒后显示;第五行和第六行在两秒后显示。