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

前言

发布-订阅模式也是经典的设计模式之一,它在前端很多地方都有应用,比如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的通信,会增加追踪和调试程序的难度
  • 增加系统复杂性:引入发布订阅模式到系统中进行消息通信,无疑会增加系统复杂度。

小结

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

相关推荐
释怀°Believe7 分钟前
Daily算法刷题【面试经典150题-7️⃣位运算/数学/】
算法·面试·职场和发展
PieroPc9 分钟前
用FastAPI 后端 和 Vue3 前端写一个博客系统 例
前端·vue·fastapi
赵民勇17 分钟前
ES5中prototype和prototype.constructor详解
javascript
xiaoyustudiowww18 分钟前
fetch异步简单版本(Tomcat 9)
java·前端·tomcat
TOPGUS18 分钟前
谷歌Chrome浏览器即将对HTTP网站设卡:突出展示“始终使用安全连接”功能
前端·网络·chrome·http·搜索引擎·seo·数字营销
C_心欲无痕25 分钟前
ts - 模板字面量类型与 `keyof` 的魔法组合:`keyof T & `on${string}`使用
linux·运维·开发语言·前端·ubuntu·typescript
Van_captain27 分钟前
rn_for_openharmony常用组件_Tabs选项卡
javascript·开源·harmonyos
赵民勇28 分钟前
ES6中的const用法详解
javascript·es6
CCPC不拿奖不改名30 分钟前
网络与API:HTTP基础+面试习题
网络·python·网络协议·学习·http·面试·职场和发展
一勺菠萝丶30 分钟前
Java 后端想学 Vue,又想写浏览器插件?
java·前端·vue.js