Article series
Javascript design pattern singleton pattern
The adaptor pattern of javascript design patterns
The Decorator pattern of javascript design patterns
Proxy mode of javascript design pattern
Comparison of javascript adaptation, proxy, and decorator patterns
State mode of javascript design mode
The iterator pattern of javascript design patterns
Policy mode of javascript design pattern
The Observer pattern of javascript design patterns
Publish subscriber mode of javascript design pattern
preface
In the last post, we talked about the observer model. This post will talk about the publis-subscribe model. One might say: Aren’t these two the same thing? Indeed there is no essential difference on the core thought and operation mechanism of these two modes. But there are some differences, otherwise I will tell you what I want to say in this article
In this paper, the code
What is the published subscriber model
Based on a topic/event channel, the object that wants to receive notifications (called Subscriber) subscribs to the topic through a custom event, and the object that has an active event (called Publisher) is notified by publishing the topic event.
The published subscriber model in life
Still remember last time that xiao Ming, xiao Hong, xiao er to the building to buy a house?
Xiao Ming recently took a look at a real estate, to the sales office was told after the house has not opened, the specific opening time has not been set. In addition to Xiao Ming, together with Xiao Hong, two people, in order to the first time that the opening time of the building, they left their phone number to the salesman Wang Wu, Wang Wu also promised that the opening of the building will send a message to inform them. After a while, the opening time of the new building was fixed, Wang Wu hurriedly took out the roster, traversed the number above, group sent a text message to inform them. It was up to these people to decide whether they would walk, drive or not
This is the observer mode.
But if Xiao Ming et al did not go to the sales office to find 50, but to the real estate website to check, that has not opened the development of the development. After the opening, Wang wu also does not send mass text messages, but synchronizes the news to the official website, so the official website automatically notifies interested buyers of the building. This is the publish subscriber model.
Key concepts are in place
Posted by: Wang Wu
Subscribers: Xiao Ming, Xiao Hong, Xiao Er
Event Center: official website
Subscribe events: Xiao Ming, Xiao Hong, Xiao Er enter the official website to pay attention to the development of the property
Notice changes: the official website automatically notifies prospective buyers of the property
What’s the difference?
- In the published subscriber mode, there is no direct dependency between the publisher and the subscriber, and it is handled through the event center.
- Publish subscriber mode – all publish/subscribe to events must go through the event center, and all “private deals” are prohibited.
Hand-published subscriber mode
Like the official website, the event center should emit events, listen on events, destroy event listeners (off), destroy all listeners (offAll), and only emit once
class EventEmitter {
constructor() {
// handleEvents is a map that stores the mapping between events and callbacks
this.handleEvents = {}
}
/** * Register an event listener, which takes the event type and callback function as arguments *@param {String} Type Event type *@param {Function} Callback callback function */
on(type, callback) {
// Check whether there is a listener queue for the event type
if (!this.handleEvents[type]) {
Uncaught TypeError: Cannot read property 'push' of undefined) Uncaught TypeError: Cannot read property 'push' of undefined
this.handleEvents[type] = []
}
// Push the callback function to the listener queue of the event type
this.handleEvents[type].push(callback)
}
/** * publish an event, which takes the event type and the listener as arguments *@param {String} Type Event type *@param {... any} Args argument list, assign the arguments passed by emit to the callback function */
emit(type, ... args) {
// Check whether the event type has a listener queue
if (this.handleEvents[type]) {
// If so, the callbacks in the queue are called one by one
this.handleEvents[type].forEach((callback) = >{ callback(... args) }) } }/** * remove the specified callback function from an event callback queue@param {String} Type Event type *@param {Function} Callback callback function */
off(type, callback) {
const callbacks = this.handleEvents[type]
const index = callbacks.indexOf(callback)
// If found, remove
if(index ! = = -1) {
callbacks.splice(index, 1)}// If the callback function for the event type is empty, the object will be deleted
if (callbacks.length === 0) {
delete this.handleEvents[type]
}
}
/** * remove all callbacks for an event@param {String} Type Event type */
offAll(type) {
if (this.handleEvents[type]) {
delete this.handleEvents[type]
}
}
/** * Register a single listener for an event@param {String} Type Event type *@param {Function} Callback callback function */
once(type, callback) {
// Wrap the callback function so that it is automatically removed after execution
const wrapper = (. args) = > {
callback.apply(args)
this.off(type, wrapper)
}
this.on(type, wrapper)
}
}
Copy the code
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 the event refresh
emitter.emit('refresh')
// Emit can also pass parameters
emitter.on('refresh'.function (pageNo, pageSize) {
console.log({pageNo:${pageNo},pageSize:${pageSize}} `)
})
emitter.emit('refresh'.'2'.'20') // Two messages are printed because two listeners of the Refresh event have been registered
// Test to remove event listener
const toBeRemovedListener = function () {
console.log('I am a listener that can be removed.')
}
emitter.on('testRemove', toBeRemovedListener)
emitter.emit('testRemove')
emitter.off('testRemove', toBeRemovedListener)
emitter.emit('testRemove') The event listener has been removed and console.log will no longer be printed
// Test to remove all refresh event listening
emitter.offAll('refresh')
console.log(emitter) // At this point, you can see that Emitter. handleEvents has become empty, and emit refresh events without any reaction
emitter.once('onlyOne'.function () {
console.info('It will only trigger once.')
})
emitter.emit('onlyOne')
emitter.emit('onlyOne') // No message will pop up
Copy the code
Publish/subscribe usage scenarios
Event listeners
// Subscribe to these functions, triggering publication when clicked, which in turn triggers these functions
$('#btn1').click(function () {
alert(1The $()})'#btn1').click(function () {
alert(2The $()})'#btn1').click(function () {
alert(3)})Copy the code
promise
Promise is the classic observer pattern: store the functions in then, reject and resovle, reject, and execute them. Collect dependencies -> trigger notifications -> fetch dependencies. You can see how to execute a handwritten 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')
Copy the code
Event 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')})// Triggers the SOME event
// And pass the parameters
emitter1.emit('some'.'zhangsan')
Copy the code
conclusion
Observer mode:
- The roles are clear, with no event scheduler acting as an intermediary, and the target objects Subject and Observer both implement the prescribed member methods.
- The two parties are more closely connected, and the target object is highly proactive, collecting and maintaining observers by itself, and proactively notifies observers of updates when the status changes.
Publish subscriber mode:
- In the publis-subscribe model, the publisher does not directly touch the subscribers, but the actual communication is done by a unified third party, who does not care about each other.
- Loose coupling, high flexibility, commonly used as an event bus
As you can see, the published subscriber model is more advanced because it is looser and has no coupling, so is the published subscriber model used more in reality? Actually, it’s not. Because in practice, our module decoupling request does not require them to be completely decoupled. If there is a stable and necessary relationship between two modules, then the observer mode should be used.
Refer to the link
Core principles and application practices of JavaScript design pattern
Talk briefly about the publish subscribe and observer patterns from an interview question
conclusion
Your “like” is my biggest affirmation, if you think it is helpful, please leave your praise, thank you!!