Skip to content

Commit

Permalink
Add observable-proxy
Browse files Browse the repository at this point in the history
Replaces the previous create-event-hub snippet with
a much more robust and interesting article.
  • Loading branch information
Chalarangelo committed May 26, 2024
1 parent 0161ce8 commit feea153
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
1 change: 1 addition & 0 deletions content/collections/js/proxy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ snippetIds:
- js/s/dynamic-getter-setter-proxy
- js/s/immutable-object-proxy
- js/s/singleton-proxy
- js/s/observable-proxy
- js/s/dynamic-getter-chain-proxy
- js/s/object-array-proxy
- js/s/proxy-array-negative-index
Expand Down
45 changes: 45 additions & 0 deletions content/snippets/js/s/observable-proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
title: Using a Proxy to implement the Observable pattern
shortTitle: Observable Proxy
type: story
language: javascript
tags: [object,proxy]
cover: city-view
excerpt: Use the Proxy object to implement the Observable pattern in JavaScript.
dateModified: 2024-05-27
---

The **Observer pattern** is a design pattern where an object (known as the subject) maintains a list of **dependents** (observers) that are notified of any changes in the object's state. With a little ingenuity, we can leverage the `EventTarget` interface and the `Proxy` object to implement the Observer pattern in JavaScript.

> [!NOTE]
>
> I'm using the `EventTarget` interface, as it's **common between the browser and Node.js** environments. If you're only working with Node.js, the `EventEmitter` offers a more robust solution, but you'll have to make a few tweaks.
At its heart the Observer pattern is a simple pub/sub ([publish–subscribe](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern)) system. We can create a `Observable` class that extends the `EventTarget` interface and use a `Proxy` object to **intercept property changes**, via the `set` trap.

When a property changes, a `CustomEvent` is created to notify any observers, carrying the **name of the property** as its `type` and the **new value** as its `detail`. Finally, the event will be **dispatched** via `EventTarget.dispatchEvent()`, **notifying all registered listeners**.

```js
class Observable extends EventTarget {
constructor() {
super();
return new Proxy(this, {
set: (target, property, value) => {
target[property] = value;
this.dispatchEvent(new CustomEvent(property, { detail: value }));
return true;
},
});
}
}

const subject = new Observable();

subject.addEventListener('name', event => {
console.log(`Name changed to ${event.detail}`);
});

subject.name = 'Alice'; // Name changed to Alice
```

While this code is pretty simple, it can be easily extend to handle more complex use cases, such as **nested objects** or **arrays**. It can be even used to create an observable store, similar to Redux. Give it a try and see how far you can take it!

0 comments on commit feea153

Please sign in to comment.