Publishing subscriber mode of javascript Design Pattern

preface

The last one talked about observer mode, and this one will talk about publish subscribe mode.
Someone may say: aren't these two the same thing? It is true that there is no essential difference in the core idea and operation mechanism of the two models.
But there are still some differences. Otherwise, I will tell you what I want to talk about

Article code

What is publish subscriber mode

Based on a topic / event channel, the objects that want to receive notification (called subscriber s) subscribe to topics through custom events, and the objects that are activated (called publisher s) are notified by publishing topic events.

Publishing subscriber model in life

Remember the last time Xiao Ming, Xiao Hong and Xiao Er went to buy a house?

Xiao Ming recently took a fancy to a real estate. When he arrived at the sales office, he was told that the house of the real estate has not been opened, and the specific opening time has not been set. In addition to Xiaoming, there are Xiaohong and Xiaoer. In order to know the opening time of the real estate, they all leave their phone number to Wang Wu, a salesman. Wang Wu also promised to inform them as soon as the real estate opened.
After a while, the opening time of the new property was set, Wang Wu quickly took out the roster, traversed the number above, and sent a group of SMS to inform them.
As for whether these people are informed to come on foot, drive or not, they decide for themselves

This is the observer model.
If Xiaoming and others didn't go to the sales office to find Wuwu, they went to the official website of the real estate to check, and learned that the real estate had not been opened, they paid attention to the progress of the real estate. After the opening, Wang Wu will not send mass SMS, but will synchronize the message to the official website, so that the official website will automatically notify the interested buyers of the property.
This is the publish subscriber model.
Key concepts

Publisher: Wang Wu
Subscribers: Xiao Ming, Xiao Hong, Xiao er
Event center: Official Website
Subscription event: Xiaoming, Xiaohong and Xiaoer enter the official website to pay attention to the development of real estate
Release event: the official website automatically informed the interested buyers of the real estate

What's the difference between the two?

  • Publish subscriber mode, there is no direct dependence between the publisher and the subscriber, all are handled through the event center.
  • In publish / subscribe mode, the publish / subscribe operations of all events must go through the event center, and all "private transactions" are prohibited

Handwritten publishing subscriber model

Compared with the official website, the event center should have the functions of emit, on, off, off all and once

class EventEmitter {
	constructor() {
		this.handleEvents = {}
	}
	on(type, callback) {
		if (!this.handleEvents[type]) {
			this.handleEvents[type] = []
		}
		this.handleEvents[type].push(callback)
	}
	emit(type, ...args) {
		if (this.handleEvents[type]) {
			this.handleEvents[type].forEach((callback) => {
				callback(...args)
			})
		}
	}
	off(type, callback) {
		const callbacks = this.handleEvents[type]
		const index = callbacks.indexOf(callback)
		if (index !== -1) {
			callbacks.splice(index, 1)
		}
		if (callbacks.length === 0) {
			delete this.handleEvents[type]
		}
	}
	offAll(type) {
		if (this.handleEvents[type]) {
			delete this.handleEvents[type]
		}
	}
	once(type, callback) {
		const wrapper = (...args) => {
			callback.apply(args)
			this.off(type, wrapper)
		}
		this.on(type, wrapper)
	}
}

test

// Create an event manager instance
const emitter = new EventEmitter()
// Register a refresh event listener
emitter.on('refresh', function () {
	console.log('Call the background to get the latest data')
})
// Publish event refresh
emitter.emit('refresh')
// You can also pass parameters by emit
emitter.on('refresh', function (pageNo, pageSize) {
	console.log(`Call background to get parameters,The parameter is:{pageNo:${pageNo},pageSize:${pageSize}}`)
})
emitter.emit('refresh', '2', '20') // At this time, two messages will be printed, because there are two listeners registered for refresh event

// Test remove event listening
const toBeRemovedListener = function () {
	console.log('I'm a listener that can be removed')
}
emitter.on('testRemove', toBeRemovedListener)
emitter.emit('testRemove')
emitter.off('testRemove', toBeRemovedListener)
emitter.emit('testRemove') // At this time, the event listener has been removed and no more console.log will be printed

// The test removes all event listeners for refresh
emitter.offAll('refresh')
console.log(emitter) // At this point, you can see that the emitter.handleEvents has become an empty object, and there will be no response to the refresh event sent by emit

emitter.once('onlyOne', function () {
	console.info('It only triggers once')
})
emitter.emit('onlyOne')
emitter.emit('onlyOne') // No message will pop up

Usage scenarios of publish subscribe mode

event listeners

// Subscribe to these functions. When you click to trigger publication, these functions will be triggered in turn
$('#btn1').click(function () {
	alert(1)
})
$('#btn1').click(function () {
	alert(2)
})
$('#btn1').click(function () {
	alert(3)
})

promise

promise is the classic scene of observer mode
First, store the functions in then, take out the functions in reset and reject, and execute the functions.
In fact, it is the way to collect dependency, trigger notification, and retrieve dependency execution
See for details Handwriting promise

jQuery.Callbacks

  // Custom event, custom callback
  var callbacks = $.Callbacks() // Note the case, C is uppercase
  callbacks.add(function (info) {
    console.info('fn1', info)
  })
  callbacks.add(function (info) {
    console.info('fn2', info)
  })
  callbacks.add(function (info) {
    console.info('fn2', info)
  })
  callbacks.fire('come')
  callbacks.fire('go')

event events in node

const EventEmitter = require('events').EventEmitter
const emitter1 = new EventEmitter()
emitter1.on('some', (name) => {
	// Listen for some events
	console.info('some event is occured 1 ' + name)
})
emitter1.on('some', () => {
	// Listen for some events
	console.info('some event is occured 2')
})
// Trigger some event
// And pass the parameters
emitter1.emit('some', 'zhangsan')

stream in node

// Steam uses custom events
const fs = require('fs')
var readStream = fs.createReadStream('./data/1.js')
var len = 0
readStream.on('data', (chunk) => {
	len += chunk.toString().length
})
readStream.on('end', () => {
	console.info('How many characters in total:' + len)
})

readLine in node

// readLine uses custom events
const fs = require('fs')
const readLine = require('readline')
var rl = readLine.createInterface({
	input: fs.createReadStream('./data/1.js')
})
var lineNum = 0
rl.on('line', (line) => {
	lineNum++
})
rl.on('close', () => {
	console.info('lineNum:' + lineNum)
})

Event BUS in Vue

Create an Event Bus (essentially a Vue instance) and export:

const EventBus = new Vue()
export default EventBus

Introduce EventBus into the main file and mount it to the global

import bus from 'EventBus File path for'
Vue.prototype.bus = bus

Subscription events:

// Here func refers to the listening function of someEvent
this.bus.$on('someEvent', func)

Release (trigger) event:

// Here params refers to the input parameter received by the callback function when the event someEvent is triggered
this.bus.$emit('someEvent', params)

summary

Observer model:

  • The role is very clear, there is no event scheduling center as the intermediary, and the target object Subject and Observer must implement the agreed member method.
  • The two sides are more closely connected, and the target object has strong initiative. They collect and maintain the observers themselves, and actively inform the observers to update when the state changes.

Publish subscriber mode:

  • In publish subscribe mode, publishers do not directly touch subscribers, but a unified third party completes the actual communication operation, and they do not care about each other.
  • Loose coupling, high flexibility, commonly used as event bus

It can be seen that the publish subscriber mode is more advanced because it is more loose and uncoupled. Is it true that publish subscriber mode is used more in reality? Not really. Because in the actual development, our module decoupling demand does not require them to be completely decoupled. If there is an association between the two modules, and this association is stable and necessary, then the observer mode should be used.

Reference link

Principle and application of JavaScript Design Pattern kernel
Talking about publish subscribe and observer mode from an interview question

epilogue

Your praise is the biggest affirmation to me. If it helps, please leave your appreciation, thank you!!!

Tags: Front-end Javascript node.js JQuery Design Pattern

Posted by gat on Thu, 13 May 2021 07:55:38 +0930