消息发布订阅的实现

实现一个 Message 类,里面包含 ondispatch 方法,实现消息的发布订阅

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,消息:绑定事件后发布的

其中,第一行和第二行立即显示;第三行和第四行在一秒后显示;第五行和第六行在两秒后显示。

版权

本作品采用 CC BY-NC-ND 4.0 授权。