⚡node系列 - 观察者模式和发布订阅是有区别的

前言

NodeJS这东西是不是学过了,之后感觉又像没学到什么东西???

我最近翻到了之前学习node的笔记,又结合了一些大佬的经验,这里把node系列相关的东西串联一下,分享给小伙伴们,顺便我自己也加深一下印象。

总共分为六篇

node打怪升级系列 - 基础篇

node打怪升级系列 - Koa篇

node打怪升级系列 - 浅谈require函数

node打怪升级系列 - 手写中间件篇

node打怪升级系列 - 手写发布订阅和观察者篇

node打怪升级系列 - 手写compose(洋葱模型)

node打怪升级系列 - 手写脚手架交互式命令界面

本文重点记录下发布订阅和观察者篇里的装备

正文开始

Node中很多内置模块,比如http net都是基于发布订阅实现的

发布订阅观察者模式其实我一直觉得它就是一种东西,直到听到一大佬说这是两种设计模式

1,发布订阅

让自定义的函数,在该执行的时候执行

EventEmitterNode中做事件驱动的,EventTarget浏览器中做事件驱动的。

两个类的宿主环境是不一样的

栗子

1.1,EventEmitter

js 复制代码
const EventEmitter = require('events').EventEmitter; 
const e = new EventEmitter()
e.on('test', (data)=>{
     console.log(data) // 1s后打印'巴拉巴拉'
})

setTimeout(function() { 
    e.emit('test', '巴拉巴拉'); 
}, 1000); 

1.2,EventTarget

js 复制代码
const e = new EventTarget();
e.addEventListener('test', (data)=>{
   console.log(data) // 1s后打印'巴拉巴拉'
})

setTimeout(function() { 
    e.dispatchEvent('test', '巴拉巴拉'); 
}, 1000); 

1.3,手戳发布订阅

顺嘴一提,构造函数都是能被new

至于构造函数是什么?new的时候发生了什么?手戳一个new,以后单独出一篇讲,此处重点围绕发布订阅

此处用构造函数的方式写

js 复制代码
function EventEmitter() {
  this.events = {} // 事件对象
}

EventEmitter.prototype.on = (eventName, cb) => {
  if (!this.events) this.events = {}
  let eventList = this.events[eventName] || (this.events[eventName] = [])
  eventList.push(cb)
}

EventEmitter.prototype.emit = (eventName, ...rest) => {
  this.events[eventName] && this.events[eventName].forEach(cb => cb(...rest));
}

发布订阅的核心就是上面这行代码啦, 是不是很简洁~~~

使用如下

要点解析

我看了半天好像只有这句话可能需要再聊下

js 复制代码
let eventList = this.events[eventName] || (this.events[eventName] = [])

等于

kotlin 复制代码
this.events[eventName] =  this.events[eventName] || []

let eventList = this.events[eventName] || []

通俗的说,这是活用引用类型里的引用关系达到简写的目的

对象属于引用类型,字符串/数字/布尔/null/undefined等属于基本类型

eventListthis.events[eventName]建立了引用关系,eventList.push(xx)就等于this.events[eventName].push(xx)

js 复制代码
let a = '哈哈'
let b = '哈哈'
let c = {}
let d = {}

累了,喝口水休息会吧

2,观察者模式

此处用的方式写

js 复制代码
// 主对象/中央厨房
class Subject {
  constructor() {
    this.deps = []
  }

  attach(customer) {
    this.deps.push(customer)
  }
  // 进行广播,通知所有顾客
  notifyAll(food) {
    this.deps.forEach((customer) => {
      if (food === customer.food) customer.update()
    })
  }
}

// 观察者/顾客
class Observer {
  constructor(name, food) {
    this.name = name
    this.food = food
  }
  update() {
    console.log(`你好 ${this.name},你的${this.food}做好了`)
  }
}

使用

csharp 复制代码
// 顾客张XX来了,点了一份宫保鸡丁
let customer1 = new Observer('张XX', '宫保鸡丁')

// 顾客李XX来了,点了一份糖醋鱼
let customer2 = new Observer('李XX', '糖醋鱼')

let subject = new Subject()

// 告诉中央厨房做一份宫保鸡丁
subject.attach(customer1)

// 告诉中央厨房做一份糖醋鱼
subject.attach(customer2)

// 糖醋鱼做好了,大喇叭响起来了,李XX 你点的糖醋鱼好了
subject.notifyAll('糖醋鱼')

3,发布订阅和观察者的区别

小伙伴们应该能发现

发布订阅模式是有一个类似第三方机构处理监听事件(on)、执行事件(emit),emit和on不存在耦合

观察者模式的主对象和观察者是有依赖关系的, 存在耦合的

完结

这篇文章我尽力把我的笔记和想法放到这了,希望对小伙伴有帮助。

欢迎转载,但请注明来源。

最后,希望小伙伴们给我个免费的点赞,祝大家心想事成,平安喜乐。

相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax