Return a cleanup/unsubscribe function from subscribe — consumers call it to remove the handler.
Details
The Observer pattern (also called pub/sub) separates the emitter (subject/observable) from its consumers (observers/subscribers). This decoupling is fundamental to event-driven architectures, reactive state systems, and streams.
Trade-offs:
If observers are not unsubscribed, the observable holds references to them — memory leak risk in SPAs
Cascade updates — one observable notifying many observers can cause complex update chains that are hard to trace
No guaranteed delivery order unless explicitly enforced
Debugging is harder than direct calls — add logging in notify() during development
When NOT to use:
When only one consumer exists — a direct callback is simpler
When the update sequence matters and subscribers need to be ordered — use a queue or middleware chain instead
For synchronous, predictable data flow — use signals or reducers
Read the instructions and examples in this document.
Apply the patterns to your implementation, adapting to your specific context.
Verify your implementation against the details and edge cases listed above.
Harness Integration
Type: knowledge — this skill is a reference document, not a procedural workflow.
No tools or state — consumed as context by other skills and agents.
Success Criteria
The patterns described in this document are applied correctly in the implementation.
Edge cases and anti-patterns listed in this document are avoided.
1---2name: js-observer-pattern3description: JS Observer Pattern4---5# JS Observer Pattern67> Notify subscribers automatically when an observable object's state changes89## When to Use1011- Multiple parts of the app need to react to the same event without coupling the emitter to its consumers12- Implementing event systems, reactive UI updates, or real-time data feeds13- Decoupling data sources from their consumers1415## Instructions16171. Create an observable with an `observers` array and `subscribe` / `unsubscribe` / `notify` methods.182. Call `notify(data)` whenever the observable's state changes — it invokes all subscribed callbacks.193. Always provide `unsubscribe` — failing to unsubscribe causes memory leaks in long-lived apps.204. In browser environments, prefer native `EventTarget` or `EventEmitter` (Node.js) over hand-rolled implementations.2122```javascript23class Observable {24 constructor() {25 this.observers = [];26 }2728 subscribe(fn) {29 this.observers.push(fn);30 return () => this.unsubscribe(fn); // return cleanup function31 }3233 unsubscribe(fn) {34 this.observers = this.observers.filter((obs) => obs !== fn);35 }3637 notify(data) {38 this.observers.forEach((fn) => fn(data));39 }40}4142const store = new Observable();43const cleanup = store.subscribe((data) => console.log('Received:', data));44store.notify({ type: 'UPDATE', payload: 42 });45cleanup(); // unsubscribe46```47485. Return a cleanup/unsubscribe function from `subscribe` — consumers call it to remove the handler.4950## Details5152The Observer pattern (also called pub/sub) separates the emitter (subject/observable) from its consumers (observers/subscribers). This decoupling is fundamental to event-driven architectures, reactive state systems, and streams.5354**Trade-offs:**5556- If observers are not unsubscribed, the observable holds references to them — memory leak risk in SPAs57- Cascade updates — one observable notifying many observers can cause complex update chains that are hard to trace58- No guaranteed delivery order unless explicitly enforced59- Debugging is harder than direct calls — add logging in `notify()` during development6061**When NOT to use:**6263- When only one consumer exists — a direct callback is simpler64- When the update sequence matters and subscribers need to be ordered — use a queue or middleware chain instead65- For synchronous, predictable data flow — use signals or reducers6667## Source6869https://patterns.dev/javascript/observer-pattern7071## Process72731. Read the instructions and examples in this document.742. Apply the patterns to your implementation, adapting to your specific context.753. Verify your implementation against the details and edge cases listed above.7677## Harness Integration7879- **Type:** knowledge — this skill is a reference document, not a procedural workflow.80- **No tools or state** — consumed as context by other skills and agents.8182## Success Criteria8384- The patterns described in this document are applied correctly in the implementation.85- Edge cases and anti-patterns listed in this document are avoided.
Run npx skillmds@latest add intense-visions/js-observer-pattern in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
JS Observer Pattern It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
Intense-Visions (@intense-visions) published this skill. Their other Agent Skills are listed on their SkillMD profile.