⚡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不存在耦合

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

完结

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

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

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

相关推荐
京东零售技术1 分钟前
京东小程序JS API仓颉改造实践
前端
奋飛10 分钟前
TypeScript系列:第六篇 - 编写高质量的TS类型
javascript·typescript·ts·declare·.d.ts
老A技术联盟10 分钟前
从小白入门,基于Cursor开发一个前端小程序之Cursor 编程实践与案例分析
前端·小程序
风铃喵游14 分钟前
构建引擎: 打造小程序编译器
前端·小程序·架构
sunbyte18 分钟前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | ThemeClock(主题时钟)
前端·javascript·css·vue.js·前端框架·tailwindcss
小飞悟27 分钟前
🎯 什么是模块化?CommonJS 和 ES6 Modules 到底有什么区别?小白也能看懂
前端·javascript·设计
浏览器API调用工程师_Taylor28 分钟前
AOP魔法:一招实现登录弹窗的全局拦截与动态处理
前端·javascript·vue.js
FogLetter29 分钟前
初识图片懒加载:让网页像"懒人"一样聪明加载
前端·javascript
微客鸟窝30 分钟前
一文搞懂NVM管理Node.js:从安装到实战全攻略
前端
归于尽30 分钟前
Cookie、Session、JWT 的前世今生
前端