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
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!!!