Observer Pattern memungkinkan satu object (subject) memberi tahu banyak object lain (observers) ketika ada perubahan state. Ini adalah pattern paling penting di JavaScript — kamu memakainya setiap hari!
Analogi: YouTube subscription. Kamu subscribe ke channel → setiap ada video baru, kamu dapat notifikasi. Tidak perlu cek manual setiap 5 menit.
Masalah yang diselesaikan:
- Bagaimana memberi tahu banyak bagian kode ketika sesuatu berubah?
- Tanpa Observer: setiap bagian harus terus-menerus mengecek (polling)
- Dengan Observer: perubahan otomatis diberitahukan ke semua yang peduli
Implementasi sederhana:
class EventEmitter {
constructor() {
this.listeners = {};
}
on(event, callback) {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event].push(callback);
}
emit(event, data) {
const callbacks = this.listeners[event] || [];
callbacks.forEach(cb => cb(data));
}
off(event, callback) {
if (!this.listeners[event]) return;
this.listeners[event] = this.listeners[event]
.filter(cb => cb !== callback);
}
}
// Penggunaan
const emitter = new EventEmitter();
emitter.on("userLogin", (user) => {
console.log(`Welcome back, ${user.name}!`);
});
emitter.on("userLogin", (user) => {
console.log(`Last login: ${user.lastLogin}`);
});
emitter.emit("userLogin", { name: "Budi", lastLogin: "2 jam lalu" });
// "Welcome back, Budi!"
// "Last login: 2 jam lalu"
Observer di JavaScript bawaan:
// DOM Events = Observer Pattern!
button.addEventListener("click", handleClick);
// button = subject, handleClick = observer
// Intersection Observer
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) loadImage(entry.target);
});
});
// MutationObserver, ResizeObserver — semua pakai pattern ini
Observer di React:
// useState + useEffect = Observer Pattern
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]); // "observe" perubahan count
// Setiap kali count berubah, effect dijalankan ulang
Observer di Node.js:
const EventEmitter = require("events");
const server = new EventEmitter();
server.on("request", (req) => console.log(`Request: ${req.url}`));
server.on("error", (err) => console.error(`Error: ${err.message}`));
// Express.js, Socket.io, Streams — semua berbasis EventEmitter
Kapan pakai Observer Pattern:
- Saat perubahan di satu tempat harus mempengaruhi banyak tempat lain
- Saat kamu butuh loose coupling — subject tidak perlu tahu detail observer
- Event handling, reactive UI, real-time notifications