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

前言

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

发布-订阅模式定义

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

发布-订阅模式实现

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

  1. 先初始化一个events对象
  2. 调用on方法时,将事件名称eventName和监听函数fn存入events对象
  3. 调用emit方法时,通过事件名称eventNameevents对象中取出对应的回调并执行
  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的通信,会增加追踪和调试程序的难度
  • 增加系统复杂性:引入发布订阅模式到系统中进行消息通信,无疑会增加系统复杂度。

小结

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

相关推荐
牧杉-惊蛰3 分钟前
纯flex布局来写瀑布流
前端·javascript·css
一袋米扛几楼981 小时前
【软件安全】什么是XSS(Cross-Site Scripting,跨站脚本)?
前端·安全·xss
向上的车轮1 小时前
Actix Web适合什么类型的Web应用?可以部署 Java 或 .NET 的应用程序?
java·前端·rust·.net
XiaoYu20021 小时前
第1章 核心竞争力和职业规划
前端·面试·程序员
excel2 小时前
🧩 深入浅出讲解:analyzeScriptBindings —— Vue 如何分析 <script> 里的变量绑定
前端
蓝瑟2 小时前
AI时代程序员如何高效提问与开发工作?
前端·ai编程
林晓lx2 小时前
使用Git钩子+ husky + lint语法检查提高前端项目代码质量
前端·git·gitlab·源代码管理
王同学要变强3 小时前
【深入学习Vue丨第二篇】构建动态Web应用的基础
前端·vue.js·学习
沐怡旸3 小时前
【穿越Effective C++】条款14:在资源管理类中小心copying行为——RAII类的拷贝语义设计
c++·面试
社恐的下水道蟑螂3 小时前
从字符串到像素:深度解析 HTML/CSS/JS 的页面渲染全过程
javascript·css·html