新手TypeScript小白之发布订阅模式

86 阅读1分钟

前言

作为一个大龄前端,终于开始学习TS了。。。恰巧也在看各种设计模式的内容,那就尝试来写一个,同事希望大家轻喷,欢迎指正。下面我开始表演(献丑)。。。

关于发布 “发布订阅模式” 与 “观察者模式” 的个人见解

个人理解发布订阅模式即,多个订阅事件与多个订阅回调函数的“多对多”关系;而观察者模式即,多个订阅回调都只能订阅指定的一个事件,即一对多关系。类比ts与js的关系,发布订阅模式是观察者模式的超集,几乎可以实现他的一切功能。

TS实现的具体代码如下

interface cache {
    [propName: string]: Array<Function>;
}
export class EventBus {
    cacheObject: cache = {}
    constructor() {
        console.log("EventBus注册成功!")
    }
    // 添加订阅
    on(key: string, cb: (...args: any[]) => void): void {
        if (typeof key !== 'string') throw new Error(`Error:订阅属性需要为字符串类型!`)
        if (cb === undefined) throw new Error(`Error:请传入订阅属性的回调函数!`)
        if (!this.cacheObject[key]) this.cacheObject[key] = []
        if (cb.name === '' || !this.cacheObject[key].includes(cb)) this.cacheObject[key].push(cb)
    }
    // 取消订阅
    off(key: string, cb: (...args: any[]) => void): void | Error {
        if (!this.cacheObject[key]) {
            throw new Error(`Error:还没有订阅${key}属性!`)
        }
        if (cb === undefined) throw new Error(`Error:请传入取消订阅属性的回调函数!`)
        for (let [index, item] of this.cacheObject[key].entries()) {
            if (item === cb) {
                this.cacheObject[key].splice(index, 1)
                break
            }
        }
    }
    // 取消指定属性下的全部订阅
    offAll(key: string): void | Error {
        if (!this.cacheObject[key]) {
            throw new Error(`Error:还没有订阅${key}属性!`)
        }
        Reflect.deleteProperty(this.cacheObject, key)
    }
    // 触发订阅
    emit(key: string, ...restParams: string[]): void | Error {
        if (!this.cacheObject[key]) {
            throw new Error(`Error:还没有订阅${key}属性!`)
        }
        for (let fn of this.cacheObject[key]) {
            if (typeof fn === 'function') {
                (<Function>fn).apply(this, restParams)
            }
        }
    }
}

好了今天就说这么多,第一次在掘金上发帖,希望大家多多指正,共同进步。撒花。。。