אירועים (EventEmitter)
הרבה מאוד ב-Node.js בנוי על אירועים: שרת "פולט" אירוע על כל בקשה, stream פולט אירוע על כל חתיכת מידע, ותהליך פולט אירוע כשהוא נסגר. המחלקה שמאחורי כל זה היא EventEmitter, ואפשר להשתמש בה גם בקוד שלכם.
האזנה ופליטה
import { EventEmitter } from 'node:events';
const store = new EventEmitter();
// האזנה: מה לעשות כשהאירוע קורה
store.on('order', (order) => {
console.log(`הזמנה חדשה: ${order.item}`);
});
// פליטה: להודיע שהאירוע קרה, עם נתונים
store.emit('order', { item: 'ספר', price: 60 });
on(name, listener)- מוסיף מאזין. אפשר כמה מאזינים לאותו אירוע, והם רצים לפי סדר ההוספה.emit(name, ...args)- מפעיל את כל המאזינים, באופן סינכרוני, עם הארגומנטים.once(name, listener)- מאזין שרץ פעם אחת בלבד ומוסר.off(name, listener)- מסיר מאזין (צריך את אותה פונקציה בדיוק).
מחלקה שפולטת אירועים
הדפוס הנפוץ: מחלקה שיורשת מ-EventEmitter, ומודיעה לעולם על מה שקורה בה. כך הקוד שמשתמש בה לא צריך לבדוק שוב ושוב אם משהו השתנה:
import { EventEmitter } from 'node:events';
class Timer extends EventEmitter {
start(seconds) {
let left = seconds;
this.emit('start', seconds);
const interval = setInterval(() => {
left -= 1;
this.emit('tick', left);
if (left === 0) {
clearInterval(interval);
this.emit('done');
}
}, 1000);
}
}
const timer = new Timer();
timer.on('tick', (left) => console.log(`נשארו ${left} שניות`));
timer.once('done', () => console.log('הזמן נגמר!'));
timer.start(3);
האירוע המיוחד: error
אם פולטים 'error' ואין אף מאזין לו, התוכנית קורסת. לכן כל אובייקט שעלול להיכשל (stream, חיבור לשרת) צריך מאזין לשגיאות:
const connection = new EventEmitter();
connection.on('error', (error) => {
console.error('החיבור נכשל:', error.message);
});
connection.emit('error', new Error('timeout')); // לא קורס, כי יש מאזין
לחכות לאירוע עם await
הפונקציה once מהמודול (לא המתודה) מחזירה Promise, וכך אפשר לחכות לאירוע בסגנון async/await:
import { once } from 'node:events';
import http from 'node:http';
const server = http.createServer((request, response) => response.end('ok'));
server.listen(3000);
await once(server, 'listening');
console.log('השרת מוכן לקבל בקשות');
איפה תפגשו אירועים
| אובייקט | אירועים נפוצים |
|---|---|
| שרת HTTP | request, listening, close |
| Stream | data, end, error |
process | exit, SIGINT (Ctrl+C), uncaughtException |
// סגירה מסודרת כשעוצרים את התוכנית
process.on('SIGINT', () => {
console.log('סוגר חיבורים...');
process.exit(0);
});
זהירות: דליפת מאזינים
מאזין שנוסף בכל בקשה ולא מוסר אף פעם מצטבר בזיכרון. אחרי 10 מאזינים לאותו אירוע Node.js מדפיס אזהרה MaxListenersExceededWarning. זה כמעט תמיד באג: הוסיפו מאזין פעם אחת, או הסירו אותו עם off כשהוא כבר לא נחוץ.
דוגמאות מלאות להרצה
event-emitter.js- on, once, error ו-await על אירועcustom-events.js- מחלקות שפולטות אירועים משלהן
בדקו את עצמכם
נסו לענות לבד לפני שאתם פותחים את התשובה.
-
מה קורה אם פולטים אירוע 'error' ואין לו מאזין?
הצגת התשובה
תשובה ג. לכן לכל אובייקט שעלול להיכשל מוסיפים on('error').
-
מה ההבדל בין
onל-once?הצגת התשובה
תשובה ב. once מתאים לאירועים שקורים פעם אחת, כמו 'ready'.