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

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

完结

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

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

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

相关推荐
程序员拂雨32 分钟前
Angular 知识框架
前端·javascript·angular.js
GoodStudyAndDayDayUp1 小时前
gitlab+portainer 实现Ruoyi Vue前端CI/CD
前端·vue.js·gitlab
程序员阿明1 小时前
vite运行只能访问localhost解决办法
前端·vue
前端 贾公子1 小时前
uniapp -- 验证码倒计时按钮组件
前端·vue.js·uni-app
zhengddzz1 小时前
从卡顿到丝滑:JavaScript性能优化实战秘籍
开发语言·javascript·性能优化
淡笑沐白1 小时前
AJAX技术全解析:从基础到最佳实践
前端·ajax
Go_going_1 小时前
ajax,Promise 和 fetch
javascript·ajax·okhttp
龙正哲2 小时前
如何在Firefox火狐浏览器里-安装梦精灵AI提示词管理工具
前端·firefox
徐徐同学2 小时前
轻量级Web画板Paint Board如何本地部署与随时随地在线绘画分享
前端
LuckyLay2 小时前
Vue百日学习计划Day4-8——Gemini版
前端·vue.js·学习