JavaScript Design Patterns: Observer Pattern

Observer

Observer is also known as publish-subscriber pattern or message mechanism. It defines a one-to-many dependency between objects. As long as the state of an object changes, all objects that depend on it are notified and It is automatically updated, which solves the functional coupling between the subject object and the observer, that is, the problem of notifying other objects when the state of one object changes.

Just looking at the definition, for the front-end friends, this concept may be relatively vague, and I still have a little understanding of the observer mode, ok, then I will look at a more appropriate example in life, I believe you will understand it immediately.

The Observer Pattern in Life

Every time Apple releases a new mobile phone, it is a hot sale. I took a fancy to the Apple 14 pro and wanted to go to an Apple store to buy it, but after I arrived at the store, the salesperson told me that this phone was very popular. Well, then I can’t come over and ask every day, it’s very time-consuming, so I leave my mobile phone number to the sales lady. If they have stock in the store, just let her call me and let me know, like this You don’t have to worry about not knowing when it will be in stock, and you don’t need to run to ask every day. If you have successfully bought a mobile phone, then the sales lady doesn’t need to notify you after that.

Isn’t this a lot clearer~ There are still many such cases, so I won’t repeat them.

Using the Observer Pattern

To tell you the truth, I can guarantee that everyone reading this article has used the observer pattern. If you don’t believe me, look at the code below:

document.querySelector('#btn').addEventListener('click',function () {         
alert('You click this button');
},false)

Does it look familiar? That’s right, our usual event binding to the DOM is a very typical publish-subscriber pattern. Here we need to monitor the user’s click event on the button, but we can’t know when the user clicks, so we subscribe to the click on the button. event, as long as the button is clicked, the button will publish the message to the subscriber, and we can do the corresponding operation.
In addition to our common DOM event binding, there are many scopes of application of the observer pattern.
For example, comparing the current popular vue frameworks, many places involve the observer mode, such as: data two-way binding

Use Object.defineProperty() to hijack the data, set up a listener Observer to monitor all properties, if the property changes, you need to tell the subscriber Watcher to update the data, and finally the command parser Compile parses the corresponding command , and then execute the corresponding update function to update the view and realize two-way binding.

Child components communicate with parent components

In Vue, we pass data from parent component to child component through props, and the child component communicates with the parent component through custom events, i.e. $on,$emit, which actually means that we publish messages through $emit and do unified processing for the subscriber $on

Next, let’s create a simple observer of our own:

First of all, we need to create an observer object, which contains a message container and three methods, namely, the subscription message method on , the unsubscribe message method off , and the sending subscription message subscribe .

https://medium.com/media/71fd8f0535321056a62935d6227f2017/href

Well, the prototype of our observer has come out, the rest is to improve the three methods inside.

Register message

The function of the registered message method is to push the message registered by the subscriber into the message queue, so two parameters need to be passed: the message type and the corresponding processing function. If it exists, create a message type and put the message into the message queue. If the message already exists, push the corresponding method into the execution method queue.

https://medium.com/media/ac05d5d5d1b3bf1f30334382797620ff/href

Publish message

Publishing a message, its function is that when the observer publishes a message, it executes the messages subscribed by all the subscribers in sequence, and also needs to pass two parameters, which are the message type and the parameters required for the corresponding execution function, of which the message type is required.

https://medium.com/media/cae03473a4d2d57ef799d0558b9a284b/href

Remove message

The function of removing the message method is to clear the message that the subscriber has logged out from the message queue. It also needs to pass two parameters, the message type and a function in the execution queue. Here, in order to avoid the situation where the message does not exist in the deletion, it is necessary to check the existence of the message.

https://medium.com/media/9228ba711ca6b5e63f68eb805cdf1621/href

ok, at this point, we have implemented a basic observer model, and then it’s time for us to show our skills.

First of all, let’s take a simple test to see how well the observer pattern we created ourselves performs?

https://medium.com/media/5b93df43b89571697ebbd45156a7275b/href

We registered two methods in the message of the message type say, one of which accepts parameters and the other does not require parameters, and then publishes the say and success messages through subscribe. The result is as we expected, the console outputs hello world and success

Two-way binding of custom data

As mentioned above, vue two-way binding is implemented by data hijacking and publish-subscribe. Now we use this idea to implement a simple two-way data binding by ourselves.

<div id="app">     
<h3>Two-way binding of data</h3>
<div class="cell">
<div class="text" v-text="myText"></div>
<input class="input" type="text" v-model="myText" > </div>
</div>

I believe you already know, what we have to do is the input of the input tag, which is bound to the div tag with the class name text through v-text

First we need to create a class, let’s call it myVue here.

https://medium.com/media/19ad9529000f1bf4aed41fa796c5b44c/href

Here we define the myVue constructor, and perform some initialization operations in the constructor. The above is annotated, and I will not repeat them here, mainly to look at the two key methods _obverse and _compile.

The first is the _observe method. Its function is to process the incoming data and redefine the set and get methods of the data to ensure that we can track and issue notifications when the data changes, mainly using Object.defineProperty()

_observe

https://medium.com/media/470b9a6f84a4e6f9128bf6137b487a81/href

Next, let’s take a look at the _compile method, which is actually a parser. Its function is to parse template instructions, bind the update function to the node corresponding to each instruction, and add subscribers to monitor data. Once the data changes, Just receive the notification, and then update the view change, the specific implementation is as follows:

_compile

https://medium.com/media/e3e45e87984ac64c897296ea27321393/href

The above code is also very clear, we recursively traverse each node starting from the root element #app, and determine whether each node has a corresponding instruction, here we only target v-text and v-model, we have carried out v-text Once new Watcher(), put it in the instruction set of myText, parsed the v-model, bound the input event to its input, and associated it with myText through new Watcher(), So we should take a look at what exactly is this Watcher?

Watcher is actually a subscriber, which is a bridge of communication between _observer and _compile to bind update functions to update DOM elements.

Warcher

https://medium.com/media/e0a1b0b37cbe926795b7ea2120c19d7c/href

Each time an instance of Watcher is created, the corresponding parameters will be passed in, and an _update operation will also be performed. In the above _compile, we have created two Watcher instances, but the two corresponding _update operations are different. For div The operation of .text is actually equivalent to div.innerHTML=h3.innerHTML = this.data.myText , for input it is equivalent to input.value=this.data.myText , so every time the data is set, we will trigger two _updates operation, update the content in the div and input respectively.

Test

https://medium.com/media/236ae68fe9daa84f827be3158b502aab/href

Now, do you have a deeper understanding of the observer pattern? In fact, I have said so much here, but it only plays a role of attracting new ideas. The important thing is the design idea. It may be difficult to learn to apply this design idea reasonably to our actual development process.


JavaScript Design Patterns: Observer Pattern was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.

Observer

Observer is also known as publish-subscriber pattern or message mechanism. It defines a one-to-many dependency between objects. As long as the state of an object changes, all objects that depend on it are notified and It is automatically updated, which solves the functional coupling between the subject object and the observer, that is, the problem of notifying other objects when the state of one object changes.

Just looking at the definition, for the front-end friends, this concept may be relatively vague, and I still have a little understanding of the observer mode, ok, then I will look at a more appropriate example in life, I believe you will understand it immediately.

The Observer Pattern in Life

Every time Apple releases a new mobile phone, it is a hot sale. I took a fancy to the Apple 14 pro and wanted to go to an Apple store to buy it, but after I arrived at the store, the salesperson told me that this phone was very popular. Well, then I can’t come over and ask every day, it’s very time-consuming, so I leave my mobile phone number to the sales lady. If they have stock in the store, just let her call me and let me know, like this You don’t have to worry about not knowing when it will be in stock, and you don’t need to run to ask every day. If you have successfully bought a mobile phone, then the sales lady doesn’t need to notify you after that.

Isn’t this a lot clearer~ There are still many such cases, so I won’t repeat them.

Using the Observer Pattern

To tell you the truth, I can guarantee that everyone reading this article has used the observer pattern. If you don’t believe me, look at the code below:

document.querySelector('#btn').addEventListener('click',function () {         
alert('You click this button');
},false)

Does it look familiar? That’s right, our usual event binding to the DOM is a very typical publish-subscriber pattern. Here we need to monitor the user’s click event on the button, but we can’t know when the user clicks, so we subscribe to the click on the button. event, as long as the button is clicked, the button will publish the message to the subscriber, and we can do the corresponding operation.
In addition to our common DOM event binding, there are many scopes of application of the observer pattern.
For example, comparing the current popular vue frameworks, many places involve the observer mode, such as: data two-way binding

Use Object.defineProperty() to hijack the data, set up a listener Observer to monitor all properties, if the property changes, you need to tell the subscriber Watcher to update the data, and finally the command parser Compile parses the corresponding command , and then execute the corresponding update function to update the view and realize two-way binding.

Child components communicate with parent components

In Vue, we pass data from parent component to child component through props, and the child component communicates with the parent component through custom events, i.e. $on,$emit, which actually means that we publish messages through $emit and do unified processing for the subscriber $on

Next, let’s create a simple observer of our own:

First of all, we need to create an observer object, which contains a message container and three methods, namely, the subscription message method on , the unsubscribe message method off , and the sending subscription message subscribe .

Well, the prototype of our observer has come out, the rest is to improve the three methods inside.

Register message

The function of the registered message method is to push the message registered by the subscriber into the message queue, so two parameters need to be passed: the message type and the corresponding processing function. If it exists, create a message type and put the message into the message queue. If the message already exists, push the corresponding method into the execution method queue.

Publish message

Publishing a message, its function is that when the observer publishes a message, it executes the messages subscribed by all the subscribers in sequence, and also needs to pass two parameters, which are the message type and the parameters required for the corresponding execution function, of which the message type is required.

Remove message

The function of removing the message method is to clear the message that the subscriber has logged out from the message queue. It also needs to pass two parameters, the message type and a function in the execution queue. Here, in order to avoid the situation where the message does not exist in the deletion, it is necessary to check the existence of the message.

ok, at this point, we have implemented a basic observer model, and then it’s time for us to show our skills.

First of all, let’s take a simple test to see how well the observer pattern we created ourselves performs?

We registered two methods in the message of the message type say, one of which accepts parameters and the other does not require parameters, and then publishes the say and success messages through subscribe. The result is as we expected, the console outputs hello world and success

Two-way binding of custom data

As mentioned above, vue two-way binding is implemented by data hijacking and publish-subscribe. Now we use this idea to implement a simple two-way data binding by ourselves.

<div id="app">     
<h3>Two-way binding of data</h3>
<div class="cell">
<div class="text" v-text="myText"></div>
<input class="input" type="text" v-model="myText" > </div>
</div>

I believe you already know, what we have to do is the input of the input tag, which is bound to the div tag with the class name text through v-text

First we need to create a class, let’s call it myVue here.

Here we define the myVue constructor, and perform some initialization operations in the constructor. The above is annotated, and I will not repeat them here, mainly to look at the two key methods _obverse and _compile.

The first is the _observe method. Its function is to process the incoming data and redefine the set and get methods of the data to ensure that we can track and issue notifications when the data changes, mainly using Object.defineProperty()

_observe

Next, let’s take a look at the _compile method, which is actually a parser. Its function is to parse template instructions, bind the update function to the node corresponding to each instruction, and add subscribers to monitor data. Once the data changes, Just receive the notification, and then update the view change, the specific implementation is as follows:

_compile

The above code is also very clear, we recursively traverse each node starting from the root element #app, and determine whether each node has a corresponding instruction, here we only target v-text and v-model, we have carried out v-text Once new Watcher(), put it in the instruction set of myText, parsed the v-model, bound the input event to its input, and associated it with myText through new Watcher(), So we should take a look at what exactly is this Watcher?

Watcher is actually a subscriber, which is a bridge of communication between _observer and _compile to bind update functions to update DOM elements.

Warcher

Each time an instance of Watcher is created, the corresponding parameters will be passed in, and an _update operation will also be performed. In the above _compile, we have created two Watcher instances, but the two corresponding _update operations are different. For div The operation of .text is actually equivalent to div.innerHTML=h3.innerHTML = this.data.myText , for input it is equivalent to input.value=this.data.myText , so every time the data is set, we will trigger two _updates operation, update the content in the div and input respectively.

Test

Now, do you have a deeper understanding of the observer pattern? In fact, I have said so much here, but it only plays a role of attracting new ideas. The important thing is the design idea. It may be difficult to learn to apply this design idea reasonably to our actual development process.


JavaScript Design Patterns: Observer Pattern was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


Print Share Comment Cite Upload Translate
APA
Maxwell | Sciencx (2024-03-28T22:01:23+00:00) » JavaScript Design Patterns: Observer Pattern. Retrieved from https://www.scien.cx/2022/10/26/javascript-design-patterns-observer-pattern/.
MLA
" » JavaScript Design Patterns: Observer Pattern." Maxwell | Sciencx - Wednesday October 26, 2022, https://www.scien.cx/2022/10/26/javascript-design-patterns-observer-pattern/
HARVARD
Maxwell | Sciencx Wednesday October 26, 2022 » JavaScript Design Patterns: Observer Pattern., viewed 2024-03-28T22:01:23+00:00,<https://www.scien.cx/2022/10/26/javascript-design-patterns-observer-pattern/>
VANCOUVER
Maxwell | Sciencx - » JavaScript Design Patterns: Observer Pattern. [Internet]. [Accessed 2024-03-28T22:01:23+00:00]. Available from: https://www.scien.cx/2022/10/26/javascript-design-patterns-observer-pattern/
CHICAGO
" » JavaScript Design Patterns: Observer Pattern." Maxwell | Sciencx - Accessed 2024-03-28T22:01:23+00:00. https://www.scien.cx/2022/10/26/javascript-design-patterns-observer-pattern/
IEEE
" » JavaScript Design Patterns: Observer Pattern." Maxwell | Sciencx [Online]. Available: https://www.scien.cx/2022/10/26/javascript-design-patterns-observer-pattern/. [Accessed: 2024-03-28T22:01:23+00:00]
rf:citation
» JavaScript Design Patterns: Observer Pattern | Maxwell | Sciencx | https://www.scien.cx/2022/10/26/javascript-design-patterns-observer-pattern/ | 2024-03-28T22:01:23+00:00
https://github.com/addpipe/simple-recorderjs-demo