面试官:请手写一个发布-订阅模式

前言

发布-订阅模式也是经典的设计模式之一,它在前端很多地方都有应用,比如javascript事件池,Vue的$on、$off,nodejs的events模块和socket通信等等都有应用,也是前端面试比较火热的考点之一,接下来给大家详细介绍下发布-订阅模式。

发布-订阅模式定义

发布-订阅模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都将得到通知。在JavaScript开发中,我们一般用事件模型来替代传统的发布-订阅模式。

发布-订阅模式实现

要手写一个简单的发布订阅模式,其实现思路如下:

  1. 先初始化一个events对象
  2. 调用on方法时,将事件名称eventName和监听函数fn存入events对象中
  3. 调用emit方法时,通过事件名称eventName从events对象中取出对应的回调并执行
  4. off方法:通过事件名称eventName找出events对象对应的监听函数并清除
  5. once方法:被emit触发一次后就立即调用off方法移除监听,也就是调用once传入的监听函数只会执行一次

代码不多,所以直接上完整代码。

js 复制代码
class EventEmitter {
    constructor() {
        this.events = {}
    }
    on(eventName, fn) {
        if (!this.events[eventName]) {
            this.events[eventName] = []
        }
        this.events[eventName].push(fn)
        return this
    }
    once(eventName, fn) {
        const func = (...args) => {
            this.off(eventName, func)
            fn.apply(this, args)
        }
        this.on(eventName, func)
        return this
    }
    emit(eventName, ...args) {
        if (!this.events[eventName]) return this
        this.events[eventName].forEach(fn => {
            fn.apply(this, args)
        });
        return this
    }
    off(eventName, fn) {
        if (!this.events[eventName]) return this
        if (typeof fn === 'function') {
            this.events[eventName] = this.events[eventName].filter((f) => f !== fn)
            return this
        }
        this.events[eventName] = null
        return this
    }
}

简单测试一下:

js 复制代码
const events = new EventEmitter();

events.on('event1', () => {
    console.log('event1', '第一个监听函数')
})
events.on('event1', () => {
    console.log('event1', '第二个监听函数')
})
events.emit('event1')

const fn1 = () => {
    console.log('event2', '第一个监听函数')
}
const fn2 = () => {
    console.log('event2', '第二个监听函数')
}
events.on('event2', fn1)
events.on('event2', fn2)
events.off('event2', fn1);

// 打印结果:
// event1 第一个监听函数
// event1 第二个监听函数

ok,大功告成了!

发布-订阅模式的作用

  • 可以广泛应用于异步编程中,这是一种替代传递回调函数的方案;
  • 可以取代对象之间硬编码的通知机制,一个对象不用再显示地调用一个对象的接口。

发布-订阅模式的优缺点

优点:

  • 解耦性:解耦了发布者和订阅者,让彼此独立,更加容易维护和扩展;
  • 异步通信:发布者和订阅者不受时间限制,可以在任意时间发布和订阅事件。

缺点:

  • 难以调试和追踪 :如果过度使用的话,系统中存在大量发布者和订阅者,会导致程序难以跟踪维护和理解。比如实际vue项目中大量运用了事件总线$bus的通信,会增加追踪和调试程序的难度。
  • 增加系统复杂性:引入发布订阅模式到系统中进行消息通信,无疑会增加系统复杂度。

小结

发布-订阅模式在各个框架源码中有非常多的应用,我们了解其内部原理和实现思路之后,其实也能帮助我们更好地去理解和使用它,同时这个也是前端面试的必备知识点之一,掌握好它准没错!

相关推荐
爱敲代码的小黄4 小时前
神经网络入门指南:从 CNN、RNN 到 Attention
人工智能·面试·程序员
LucianaiB6 小时前
【元宝搜索开发者征文大赛】AI时代,学得慢就不用学?用元宝搜索打造一个教程保质期,确保每一个教程符合你的现状
前端·人工智能·ai编程
excel6 小时前
JavaScript 对象池:减少高频对象创建与 GC 压力
前端
陈随易8 小时前
纯 Go 写的 JS 引擎,跑分超过了 C 语言的 QuickJS
前端·后端·程序员
子兮曰9 小时前
Chrome 权限元素实战:144 与 151 的渐进增强写法
前端·javascript·chrome
IT_陈寒10 小时前
Redis连接池泄漏那次,我差点把生产环境搞崩了
前端·人工智能·后端
强尼银手10 小时前
我花一天做了个格斗游戏原型,判定全对,然后被「美术」劝退了
前端·javascript
石小石Orz10 小时前
AI 正在蚕食我们的编码能力
前端·后端·算法
陈随易10 小时前
专注飞机 FocusFlight,两个人把番茄钟做成了一趟航班
前端·后端·程序员
总要学点什么11 小时前
第98篇:三维特效-材质线效果——给一条线换十种材质,虚线的图案只填了一半
开发语言·前端·javascript·ecmascript·gis·webgl·材质