الأحداث
[مستقر: 2 - مستقر]
مستقر: 2 الاستقرار: 2 - مستقر
شفرة المصدر: lib/events.js
تم بناء جزء كبير من واجهة برمجة تطبيقات Node.js الأساسية حول بنية غير متزامنة قائمة على الأحداث اصطلاحية، حيث تقوم أنواع معينة من الكائنات (تسمى "الباعثات") بإطلاق أحداث مسماة تتسبب في استدعاء كائنات Function ("المستمعون").
على سبيل المثال: يقوم كائن net.Server بإطلاق حدث في كل مرة يتصل به نظير؛ يقوم fs.ReadStream بإطلاق حدث عند فتح الملف؛ يقوم stream بإطلاق حدث كلما توفرت بيانات للقراءة.
جميع الكائنات التي تطلق الأحداث هي مثيلات للفئة EventEmitter. تعرض هذه الكائنات وظيفة eventEmitter.on() التي تسمح بإرفاق دالة واحدة أو أكثر بالأحداث المسماة التي تطلقها الكائن. عادةً ما تكون أسماء الأحداث عبارة عن سلاسل مكتوبة بأحرف الجمل ولكن يمكن استخدام أي مفتاح خاصية JavaScript صالح.
عندما يطلق كائن EventEmitter حدثًا، يتم استدعاء جميع الدوال المرفقة بهذا الحدث المحدد بشكل متزامن. يتم تجاهل أي قيم تم إرجاعها بواسطة المستمعين الذين تم استدعاؤهم والتخلص منها.
يوضح المثال التالي مثيل EventEmitter بسيطًا مع مستمع واحد. تُستخدم طريقة eventEmitter.on() لتسجيل المستمعين، بينما تُستخدم طريقة eventEmitter.emit() لتشغيل الحدث.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('حدث!');
});
myEmitter.emit('event');const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('حدث!');
});
myEmitter.emit('event');تمرير الوسائط وthis إلى المستمعين
تسمح طريقة eventEmitter.emit() بتمرير مجموعة عشوائية من الوسائط إلى دوال المستمع. ضع في اعتبارك أنه عند استدعاء دالة مستمع عادية، يتم تعيين الكلمة الأساسية this القياسية عن قصد للإشارة إلى مثيل EventEmitter الذي تم إرفاق المستمع به.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// يطبع:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
});
myEmitter.emit('event', 'a', 'b');const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// يطبع:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
});
myEmitter.emit('event', 'a', 'b');من الممكن استخدام دوال ES6 Arrow كمستمعين، ومع ذلك، عند القيام بذلك، لن تشير الكلمة الأساسية this بعد الآن إلى مثيل EventEmitter:
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// يطبع: a b غير معرف
});
myEmitter.emit('event', 'a', 'b');const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// يطبع: a b {}
});
myEmitter.emit('event', 'a', 'b');غير متزامن مقابل متزامن
يستدعي EventEmitter جميع المستمعين بشكل متزامن بالترتيب الذي تم تسجيلهم به. يضمن هذا التسلسل المناسب للأحداث ويساعد على تجنب حالات السباق وأخطاء المنطق. عند الاقتضاء، يمكن لوظائف المستمع التبديل إلى وضع التشغيل غير المتزامن باستخدام طرق setImmediate() أو process.nextTick():
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('this happens asynchronously');
});
});
myEmitter.emit('event', 'a', 'b');const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('this happens asynchronously');
});
});
myEmitter.emit('event', 'a', 'b');معالجة الأحداث مرة واحدة فقط
عندما يتم تسجيل مستمع باستخدام طريقة eventEmitter.on()، يتم استدعاء هذا المستمع في كل مرة يتم فيها إصدار الحدث المسمى.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2باستخدام طريقة eventEmitter.once()، من الممكن تسجيل مستمع يتم استدعاؤه مرة واحدة على الأكثر لحدث معين. بمجرد إصدار الحدث، يتم إلغاء تسجيل المستمع و ثم يتم استدعاؤه.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignoredconst EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignoredأحداث الخطأ
عند حدوث خطأ داخل نسخة EventEmitter، فإن الإجراء النموذجي هو إطلاق حدث 'error'. يتم التعامل مع هذه الحالات كحالات خاصة داخل Node.js.
إذا لم يكن لدى EventEmitter مستمع واحد على الأقل مسجل لحدث 'error'، وتم إطلاق حدث 'error'، فسيتم طرح الخطأ، وطباعة تتبع المكدس، وخروج عملية Node.js.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// يطرح الخطأ ويتسبب في تعطل Node.jsconst EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// يطرح الخطأ ويتسبب في تعطل Node.jsللحماية من تعطل عملية Node.js، يمكن استخدام وحدة domain. (لاحظ، مع ذلك، أن وحدة node:domain مهجورة.)
كأفضل ممارسة، يجب دائمًا إضافة مستمعين لأحداث 'error'.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// يطبع: whoops! there was an errorconst EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// يطبع: whoops! there was an errorمن الممكن مراقبة أحداث 'error' دون استهلاك الخطأ الذي تم إطلاقه عن طريق تثبيت مستمع باستخدام الرمز events.errorMonitor.
import { EventEmitter, errorMonitor } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// لا يزال يطرح الخطأ ويتسبب في تعطل Node.jsconst { EventEmitter, errorMonitor } = require('node:events');
const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// لا يزال يطرح الخطأ ويتسبب في تعطل Node.jsالتقاط رفض الوعود
يُعد استخدام الدوال async مع معالجات الأحداث إشكاليًا، لأنه قد يؤدي إلى رفض غير معالج في حالة وجود استثناء تم إطلاقه:
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
ee.on('something', async (value) => {
throw new Error('kaboom');
});const EventEmitter = require('node:events');
const ee = new EventEmitter();
ee.on('something', async (value) => {
throw new Error('kaboom');
});يعمل الخيار captureRejections في مُنشئ EventEmitter أو تغيير الإعداد العالمي على تغيير هذا السلوك، عن طريق تثبيت معالج .then(undefined, handler) على Promise. يقوم هذا المعالج بتوجيه الاستثناء بشكل غير متزامن إلى طريقة Symbol.for('nodejs.rejection') إذا كانت موجودة، أو إلى معالج حدث 'error' إذا لم يكن موجودًا.
import { EventEmitter } from 'node:events';
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
throw new Error('kaboom');
});
ee2[Symbol.for('nodejs.rejection')] = console.log;const EventEmitter = require('node:events');
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
throw new Error('kaboom');
});
ee2[Symbol.for('nodejs.rejection')] = console.log;سيؤدي تعيين events.captureRejections = true إلى تغيير الإعداد الافتراضي لجميع مثيلات EventEmitter الجديدة.
import { EventEmitter } from 'node:events';
EventEmitter.captureRejections = true;
const ee1 = new EventEmitter();
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);const events = require('node:events');
events.captureRejections = true;
const ee1 = new events.EventEmitter();
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);أحداث 'error' التي يتم إنشاؤها بواسطة سلوك captureRejections ليس لديها معالج catch لتجنب حلقات الخطأ اللانهائية: التوصية هي عدم استخدام دوال async كمعالجات أحداث 'error'.
الفئة: EventEmitter
[سجل التغييرات]
| الإصدار | التغييرات |
|---|---|
| v13.4.0, v12.16.0 | تمت إضافة خيار captureRejections. |
| v0.1.26 | تمت الإضافة في: v0.1.26 |
يتم تعريف الفئة EventEmitter وعرضها بواسطة الوحدة node:events:
import { EventEmitter } from 'node:events';const EventEmitter = require('node:events');تقوم جميع EventEmitters بإصدار الحدث 'newListener' عند إضافة مستمعين جدد والحدث 'removeListener' عند إزالة المستمعين الحاليين.
وهي تدعم الخيار التالي:
captureRejections<boolean> إنه يمكّن الالتقاط التلقائي لرفض الوعد. افتراضي:false.
الحدث: 'newListener'
تمت الإضافة في: v0.1.26
eventName<string> | <symbol> اسم الحدث الذي يتم الاستماع إليهlistener<Function> دالة معالج الأحداث
سيصدر مثيل EventEmitter حدثه الخاص 'newListener' قبل إضافة مستمع إلى المصفوفة الداخلية للمستمعين.
يتم تمرير اسم الحدث ومرجع إلى المستمع الذي تتم إضافته إلى المستمعين المسجلين للحدث 'newListener'.
حقيقة أن الحدث يتم تشغيله قبل إضافة المستمع له تأثير جانبي دقيق ولكنه مهم: يتم إدراج أي مستمعين إضافيين مسجلين لنفس name داخل رد الاتصال 'newListener' قبل المستمع الذي هو قيد الإضافة.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// قم بذلك مرة واحدة فقط حتى لا نكرر إلى الأبد
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// إدراج مستمع جديد في المقدمة
myEmitter.on('event', () => {
console.log('B');
});
}
});
myEmitter.on('event', () => {
console.log('A');
});
myEmitter.emit('event');
// يطبع:
// B
// Aconst EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// قم بذلك مرة واحدة فقط حتى لا نكرر إلى الأبد
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// إدراج مستمع جديد في المقدمة
myEmitter.on('event', () => {
console.log('B');
});
}
});
myEmitter.on('event', () => {
console.log('A');
});
myEmitter.emit('event');
// يطبع:
// B
// Aالحدث: 'removeListener'
[التاريخ]
| الإصدار | التغييرات |
|---|---|
| v6.1.0, v4.7.0 | بالنسبة للمستمعين المرفقين باستخدام .once()، تعطي وسيطة listener الآن دالة المستمع الأصلية. |
| v0.9.3 | تمت إضافته في: v0.9.3 |
eventName<string> | <symbol> اسم الحدثlistener<Function> دالة معالج الحدث
يتم إطلاق حدث 'removeListener' بعد إزالة listener.
emitter.addListener(eventName, listener)
تمت إضافته في: v0.1.26
eventName<string> | <symbol>listener<Function>
اسم مستعار لـ emitter.on(eventName, listener).
emitter.emit(eventName[, ...args])
تمت إضافته في: v0.1.26
يستدعي بشكل متزامن كل المستمعين المسجلين للحدث المسمى eventName، بالترتيب الذي تم تسجيلهم به، ويمرر الوسائط المقدمة لكل منهم.
يُرجع true إذا كان للحدث مستمعين، و false بخلاف ذلك.
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listenerconst EventEmitter = require('node:events');
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listeneremitter.eventNames()
تمت الإضافة في: الإصدار 6.0.0
- يُرجع: <Array>
يُرجع مصفوفة تسرد الأحداث التي سجل المُصدر مستمعين لها. القيم في المصفوفة هي سلاسل أو Symbol.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]const EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]emitter.getMaxListeners()
تمت الإضافة في: الإصدار 1.0.0
- يُرجع: <integer>
يُرجع قيمة الحد الأقصى الحالي للمستمعين لـ EventEmitter والذي يتم تعيينه إما بواسطة emitter.setMaxListeners(n) أو افتراضيًا إلى events.defaultMaxListeners.
emitter.listenerCount(eventName[, listener])
[التاريخ]
| الإصدار | التغييرات |
|---|---|
| v19.8.0, v18.16.0 | تمت إضافة وسيطة listener. |
| v3.2.0 | تمت الإضافة في: الإصدار 3.2.0 |
eventName<string> | <symbol> اسم الحدث الذي يتم الاستماع إليهlistener<Function> دالة معالج الحدث- يُرجع: <integer>
يُرجع عدد المستمعين الذين يستمعون إلى الحدث المسمى eventName. إذا تم توفير listener، فسوف يُرجع عدد المرات التي تم فيها العثور على المستمع في قائمة مستمعي الحدث.
emitter.listeners(eventName)
[سجل التعديلات]
| الإصدار | التغييرات |
|---|---|
| v7.0.0 | بالنسبة للمستمعين المرفقين باستخدام .once()، يعيد هذا المستمعين الأصليين بدلًا من وظائف التغليف الآن. |
| v0.1.26 | تمت إضافته في: v0.1.26 |
eventName<string> | <symbol>- القيمة المعادة: <Function[]>
إرجاع نسخة من مصفوفة المستمعين للحدث المسمى eventName.
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]emitter.off(eventName, listener)
تمت إضافته في: v10.0.0
eventName<string> | <symbol>listener<Function>- القيمة المعادة: <EventEmitter>
اسم مستعار لـ emitter.removeListener().
emitter.on(eventName, listener)
تمت إضافته في: v0.1.101
eventName<string> | <symbol> اسم الحدث.listener<Function> دالة الاستدعاء- القيمة المعادة: <EventEmitter>
إضافة الدالة listener إلى نهاية مصفوفة المستمعين للحدث المسمى eventName. لا يتم إجراء أي فحوصات للتأكد مما إذا كان قد تمت إضافة listener بالفعل. ستؤدي المكالمات المتعددة التي تمرر نفس المجموعة من eventName و listener إلى إضافة listener واستدعائها عدة مرات.
server.on('connection', (stream) => {
console.log('someone connected!');
});إرجاع مرجع إلى EventEmitter، بحيث يمكن تسلسل الاستدعاءات.
بشكل افتراضي، يتم استدعاء مستمعي الأحداث بالترتيب الذي تتم إضافتهم به. يمكن استخدام الطريقة emitter.prependListener() كبديل لإضافة مستمع الحدث إلى بداية مصفوفة المستمعين.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// aconst EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// aemitter.once(eventName, listener)
تمت الإضافة في: v0.3.0
eventName<string> | <symbol> اسم الحدث.listener<Function> وظيفة الاستدعاء- الإرجاع: <EventEmitter>
يضيف وظيفة listener لمرة واحدة للحدث المسمى eventName. في المرة التالية التي يتم فيها تشغيل eventName، تتم إزالة هذا المستمع ثم استدعاؤه.
server.once('connection', (stream) => {
console.log('Ah, we have our first user!');
});يُرجع مرجعًا إلى EventEmitter، بحيث يمكن ربط الاستدعاءات.
بشكل افتراضي، يتم استدعاء مستمعي الأحداث بالترتيب الذي تتم إضافتهم به. يمكن استخدام الطريقة emitter.prependOnceListener() كبديل لإضافة مستمع الحدث إلى بداية مصفوفة المستمعين.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// aconst EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// aemitter.prependListener(eventName, listener)
تمت الإضافة في: v6.0.0
eventName<string> | <symbol> اسم الحدث.listener<Function> وظيفة الاستدعاء- الإرجاع: <EventEmitter>
يضيف وظيفة listener إلى بداية مصفوفة المستمعين للحدث المسمى eventName. لا يتم إجراء أي فحوصات لمعرفة ما إذا كان قد تمت إضافة listener بالفعل. ستؤدي المكالمات المتعددة التي تمرر نفس المجموعة من eventName و listener إلى إضافة listener واستدعائها عدة مرات.
server.prependListener('connection', (stream) => {
console.log('someone connected!');
});يُرجع مرجعًا إلى EventEmitter، بحيث يمكن ربط الاستدعاءات.
emitter.prependOnceListener(eventName, listener)
تمت الإضافة في: الإصدار 6.0.0
eventName<string> | <symbol> اسم الحدث.listener<Function> دالة الاستدعاء- الإرجاع: <EventEmitter>
يضيف دالة listener لمرة واحدة للحدث المسمى eventName إلى بداية مصفوفة المستمعين. في المرة التالية التي يتم فيها تشغيل eventName، تتم إزالة هذا المستمع، ثم يتم استدعاؤه.
server.prependOnceListener('connection', (stream) => {
console.log('Ah, we have our first user!');
});يقوم بإرجاع مرجع إلى EventEmitter، بحيث يمكن ربط الاستدعاءات.
emitter.removeAllListeners([eventName])
تمت الإضافة في: الإصدار 0.1.26
eventName<string> | <symbol>- الإرجاع: <EventEmitter>
يزيل جميع المستمعين، أو مستمعي eventName المحدد.
من الممارسات السيئة إزالة المستمعين الذين تمت إضافتهم في مكان آخر في التعليمات البرمجية، خاصةً عندما تم إنشاء مثيل EventEmitter بواسطة مكون أو وحدة نمطية أخرى (مثل مآخذ التوصيل أو تدفقات الملفات).
يقوم بإرجاع مرجع إلى EventEmitter، بحيث يمكن ربط الاستدعاءات.
emitter.removeListener(eventName, listener)
تمت الإضافة في: الإصدار 0.1.26
eventName<string> | <symbol>listener<Function>- الإرجاع: <EventEmitter>
يزيل listener المحدد من مصفوفة المستمعين للحدث المسمى eventName.
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);ستزيل removeListener() على الأكثر نسخة واحدة من المستمع من مصفوفة المستمعين. إذا تمت إضافة أي مستمع واحد عدة مرات إلى مصفوفة المستمعين لـ eventName المحدد، فيجب استدعاء removeListener() عدة مرات لإزالة كل نسخة.
بمجرد انبعاث حدث ما، يتم استدعاء جميع المستمعين المرفقين به في وقت الانبعاث بالترتيب. وهذا يعني أن أي استدعاءات removeListener() أو removeAllListeners() بعد الانبعاث و قبل انتهاء تنفيذ آخر مستمع لن تزيلهم من emit() قيد التقدم. تتصرف الأحداث اللاحقة كما هو متوقع.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// Aconst EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// Aنظرًا لأن المستمعين تتم إدارتهم باستخدام مصفوفة داخلية، فإن استدعاء هذا سيؤدي إلى تغيير مؤشرات موضع أي مستمع مسجل بعد المستمع الذي تتم إزالته. لن يؤثر هذا على الترتيب الذي يتم به استدعاء المستمعين، ولكنه يعني أن أي نسخ من مصفوفة المستمعين كما تم إرجاعها بواسطة طريقة emitter.listeners() ستحتاج إلى إعادة إنشائها.
عندما تتم إضافة دالة واحدة كمعالج عدة مرات لحدث واحد (كما في المثال أدناه)، ستزيل removeListener() آخر نسخة تمت إضافتها. في المثال، تتم إزالة المستمع once('ping'):
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');const EventEmitter = require('node:events');
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');يقوم بإرجاع مرجع إلى EventEmitter، بحيث يمكن ربط الاستدعاءات.
emitter.setMaxListeners(n)
أُضيف في: v0.3.5
n<integer>- Returns: <EventEmitter>
بشكل افتراضي، ستطبع EventEmitter تحذيرًا إذا تمت إضافة أكثر من 10 مستمعين لحدث معين. هذا افتراضي مفيد يساعد في العثور على تسربات الذاكرة. يسمح الأسلوب emitter.setMaxListeners() بتعديل الحد الأقصى لهذا المثيل المحدد EventEmitter. يمكن تعيين القيمة إلى Infinity (أو 0) للإشارة إلى عدد غير محدود من المستمعين.
إرجاع مرجع إلى EventEmitter، بحيث يمكن تسلسل الاستدعاءات.
emitter.rawListeners(eventName)
أُضيف في: v9.4.0
eventName<string> | <symbol>- Returns: <Function[]>
إرجاع نسخة من مصفوفة المستمعين للحدث المسمى eventName، بما في ذلك أي أغلفة (مثل تلك التي تم إنشاؤها بواسطة .once()).
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])
::: معلومات [السجل]
| الإصدار | التغييرات |
|---|---|
| v17.4.0, v16.14.0 | لم تعد تجريبية. |
| v13.4.0, v12.16.0 | تمت إضافتها في: v13.4.0, v12.16.0 |
| ::: |
يتم استدعاء الأسلوب Symbol.for('nodejs.rejection') في حالة حدوث رفض وعد عند إصدار حدث وتم تمكين captureRejections على المُصدِر. من الممكن استخدام events.captureRejectionSymbol بدلاً من Symbol.for('nodejs.rejection').
::: group-code
import { EventEmitter, captureRejectionSymbol } from 'node:events';
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true });
}
[captureRejectionSymbol](err, event, ...args) {
console.log('حدث رفض لـ', event, 'مع', err, ...args);
this.destroy(err);
}
destroy(err) {
// قم بإيقاف تشغيل المورد هنا.
}
}const { EventEmitter, captureRejectionSymbol } = require('node:events');
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true });
}
[captureRejectionSymbol](err, event, ...args) {
console.log('حدث رفض لـ', event, 'مع', err, ...args);
this.destroy(err);
}
destroy(err) {
// قم بإيقاف تشغيل المورد هنا.
}
}:::
events.defaultMaxListeners
تمت إضافتها في: v0.11.2
افتراضيًا، يمكن تسجيل عدد أقصاه 10 مستمعين لأي حدث واحد. يمكن تغيير هذا الحد لنسخ EventEmitter الفردية باستخدام الأسلوب emitter.setMaxListeners(n). لتغيير الإعداد الافتراضي لجميع نسخ EventEmitter، يمكن استخدام الخاصية events.defaultMaxListeners. إذا لم تكن هذه القيمة عددًا موجبًا، يتم طرح RangeError.
توخ الحذر عند تعيين events.defaultMaxListeners لأن التغيير يؤثر على جميع نسخ EventEmitter، بما في ذلك تلك التي تم إنشاؤها قبل إجراء التغيير. ومع ذلك، فإن استدعاء emitter.setMaxListeners(n) لا يزال له الأسبقية على events.defaultMaxListeners.
هذا ليس حدًا صارمًا. ستسمح نسخة EventEmitter بإضافة المزيد من المستمعين ولكنها ستخرج تحذير تتبع إلى stderr يشير إلى أنه تم اكتشاف "تسرب ذاكرة محتمل لـ EventEmitter". بالنسبة لأي EventEmitter فردي، يمكن استخدام الأسلوبين emitter.getMaxListeners() و emitter.setMaxListeners() لتجنب هذا التحذير مؤقتًا:
ليس لـ defaultMaxListeners أي تأثير على نسخ AbortSignal. في حين أنه لا يزال من الممكن استخدام emitter.setMaxListeners(n) لتعيين حد تحذير لنسخ AbortSignal الفردية، افتراضيًا لن تحذر نسخ AbortSignal.
::: group-code
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// قم بالأشياء
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// قم بالأشياء
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});:::
يمكن استخدام علامة سطر الأوامر --trace-warnings لعرض تتبع المكدس لهذه التحذيرات.
يمكن فحص التحذير الصادر باستخدام process.on('warning') وسيكون له خصائص إضافية emitter و type و count، تشير إلى نسخة باعث الحدث واسم الحدث وعدد المستمعين المرفقين على التوالي. تم تعيين الخاصية name الخاصة به على 'MaxListenersExceededWarning'.
events.errorMonitor
أُضيف في: v13.6.0, v12.17.0
يجب استخدام هذا الرمز لتثبيت مستمع لمراقبة أحداث 'error' فقط. يتم استدعاء المستمعين المثبتين باستخدام هذا الرمز قبل استدعاء مستمعي 'error' العاديين.
لا يؤدي تثبيت مستمع باستخدام هذا الرمز إلى تغيير السلوك بمجرد انبعاث حدث 'error'. لذلك ، ستظل العملية معطلة إذا لم يتم تثبيت أي مستمع 'error' عادي.
events.getEventListeners(emitterOrTarget, eventName)
أُضيف في: v15.2.0, v14.17.0
emitterOrTarget<EventEmitter> | <EventTarget>eventName<string> | <symbol>- الإرجاع: <Function[]>
إرجاع نسخة من مصفوفة المستمعين للحدث المسمى eventName.
بالنسبة إلى EventEmitters ، يتصرف هذا تمامًا مثل استدعاء .listeners على الباعث.
بالنسبة إلى EventTargets ، هذه هي الطريقة الوحيدة للحصول على مستمعي الأحداث للهدف الحدث. هذا مفيد لأغراض التصحيح والتشخيص.
import { getEventListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}const { getEventListeners, EventEmitter } = require('node:events');
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}events.getMaxListeners(emitterOrTarget)
أُضيف في: v19.9.0, v18.17.0
emitterOrTarget<EventEmitter> | <EventTarget>- القيمة المُعادة: <number>
تُعيد الحد الأقصى المُعيّن حاليًا لعدد المستمعين.
بالنسبة إلى EventEmitter، يتصرف هذا تمامًا مثل استدعاء .getMaxListeners على الباعث.
بالنسبة إلى EventTarget، هذه هي الطريقة الوحيدة للحصول على الحد الأقصى لمستمعي الأحداث لهدف الحدث. إذا تجاوز عدد معالجات الأحداث على EventTarget واحد الحد الأقصى المُعيّن، فستطبع EventTarget تحذيرًا.
import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}const { getMaxListeners, setMaxListeners, EventEmitter } = require('node:events');
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}events.once(emitter, name[, options])
[سجل التغييرات]
| الإصدار | التغييرات |
|---|---|
| v15.0.0 | خيار signal مدعوم الآن. |
| v11.13.0, v10.16.0 | أُضيف في: v11.13.0, v10.16.0 |
emitter<EventEmitter>options<Object>signal<AbortSignal> يمكن استخدامه لإلغاء انتظار الحدث.
القيمة المُعادة: <Promise>
تُنشئ Promise يتم استيفائها عندما يُصدر EventEmitter الحدث المحدد أو يتم رفضها إذا كان EventEmitter يُصدر 'error' أثناء الانتظار. ستحل Promise مع مجموعة من جميع الوسائط الصادرة إلى الحدث المحدد.
هذه الطريقة عامة عن قصد وتعمل مع واجهة EventTarget لمنصة الويب، والتي لا تحتوي على دلالات حدث 'error' خاصة ولا تستمع إلى حدث 'error'.
import { once, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}const { once, EventEmitter } = require('node:events');
async function run() {
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}
}
run();يتم استخدام المعالجة الخاصة لحدث 'error' فقط عندما يتم استخدام events.once() للانتظار لحدث آخر. إذا تم استخدام events.once() للانتظار لحدث 'error' نفسه، فإنه يتم التعامل معه كأي نوع آخر من الأحداث بدون معالجة خاصة:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boomconst { EventEmitter, once } = require('node:events');
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boomيمكن استخدام <AbortSignal> لإلغاء انتظار الحدث:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Prints: Waiting for the event was canceled!const { EventEmitter, once } = require('node:events');
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Prints: Waiting for the event was canceled!انتظار أحداث متعددة مُصدرة على process.nextTick()
هناك حالة حافة تستحق الملاحظة عند استخدام الدالة events.once() لانتظار أحداث متعددة مُصدرة في نفس دفعة عمليات process.nextTick()، أو متى تم إصدار أحداث متعددة بشكل متزامن. على وجه التحديد، نظرًا لأن قائمة انتظار process.nextTick() يتم استنزافها قبل قائمة انتظار المهام الصغيرة Promise، ولأن EventEmitter تُصدر جميع الأحداث بشكل متزامن، فمن الممكن أن تفوت events.once() حدثًا ما.
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function foo() {
await once(myEE, 'bar');
console.log('bar');
// لن يتم حل هذا الوعد أبدًا لأن حدث 'foo'
// سيكون قد تم إصداره بالفعل قبل إنشاء الوعد.
await once(myEE, 'foo');
console.log('foo');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function foo() {
await once(myEE, 'bar');
console.log('bar');
// لن يتم حل هذا الوعد أبدًا لأن حدث 'foo'
// سيكون قد تم إصداره بالفعل قبل إنشاء الوعد.
await once(myEE, 'foo');
console.log('foo');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));لإلتقاط كلا الحدثين، قم بإنشاء كل وعد قبل انتظار أي منهما، ثم يصبح من الممكن استخدام Promise.all() أو Promise.race() أو Promise.allSettled():
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));events.captureRejections
[السجل]
| الإصدار | التغييرات |
|---|---|
| v17.4.0, v16.14.0 | لم يعد تجريبيًا. |
| v13.4.0, v12.16.0 | تمت إضافته في: v13.4.0, v12.16.0 |
القيمة: <boolean>
لتغيير الخيار الافتراضي captureRejections في جميع كائنات EventEmitter الجديدة.
events.captureRejectionSymbol
[السجل]
| الإصدار | التغييرات |
|---|---|
| v17.4.0, v16.14.0 | لم يعد تجريبيًا. |
| v13.4.0, v12.16.0 | تمت إضافته في: v13.4.0, v12.16.0 |
القيمة: Symbol.for('nodejs.rejection')
راجع كيفية كتابة معالج رفض مخصص.
events.listenerCount(emitter, eventName)
تمت إضافته في: v0.9.12
تم الإيقاف منذ: v3.2.0
[ثابت: 0 - تم الإيقاف]
ثابت: 0 الاستقرار: 0 - تم الإيقاف: استخدم emitter.listenerCount() بدلاً من ذلك.
emitter<EventEmitter> المُرسِل المراد الاستعلام عنهeventName<string> | <symbol> اسم الحدث
طريقة فئة تُرجع عدد المستمعين لـ eventName المُسجل في emitter المحدد.
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2const { EventEmitter, listenerCount } = require('node:events');
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2events.on(emitter, eventName[, options])
[السجل]
| الإصدار | التغييرات |
|---|---|
| v22.0.0, v20.13.0 | دعم خيارات highWaterMark و lowWaterMark، للتناسق. الخيارات القديمة لا تزال مدعومة. |
| v20.0.0 | خيارات close و highWatermark و lowWatermark مدعومة الآن. |
| v13.6.0, v12.16.0 | تمت إضافته في: v13.6.0, v12.16.0 |
emitter<EventEmitter>eventName<string> | <symbol> اسم الحدث الذي يتم الاستماع إليهoptions<Object>signal<AbortSignal> يمكن استخدامه لإلغاء انتظار الأحداث.close- <string[]> أسماء الأحداث التي ستنهي التكرار.highWaterMark- <integer> الافتراضي:Number.MAX_SAFE_INTEGERالعلامة المائية العليا. يتم إيقاف المرسل مؤقتًا في كل مرة يكون فيها حجم الأحداث المخزنة مؤقتًا أعلى منه. مدعوم فقط على المرسلين الذين ينفذون طرقpause()وresume().lowWaterMark- <integer> الافتراضي:1العلامة المائية السفلى. يتم استئناف المرسل في كل مرة يكون فيها حجم الأحداث المخزنة مؤقتًا أقل منه. مدعوم فقط على المرسلين الذين ينفذون طرقpause()وresume().
الإرجاع: <AsyncIterator> يقوم بتكرار أحداث
eventNameالمنبعثة منemitter
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable hereconst { on, EventEmitter } = require('node:events');
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();إرجاع AsyncIterator يقوم بتكرار أحداث eventName. سيتم طرح خطأ إذا أصدر EventEmitter الحدث 'error'. يزيل جميع المستمعين عند الخروج من الحلقة. value الذي تم إرجاعه بواسطة كل تكرار هو مصفوفة تتكون من وسيطات الحدث المنبعثة.
يمكن استخدام <AbortSignal> لإلغاء الانتظار على الأحداث:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());const { on, EventEmitter } = require('node:events');
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());events.setMaxListeners(n[, ...eventTargets])
أضيف في: v15.4.0
n<number> رقم غير سالب. الحد الأقصى لعدد المستمعين لكل حدثEventTarget....eventsTargets<EventTarget[]> | <EventEmitter[]> صفر أو أكثر من نسخ <EventTarget> أو <EventEmitter>. إذا لم يتم تحديد أي منها، يتم تعيينnكحد أقصى افتراضي لجميع كائنات <EventTarget> و <EventEmitter> التي تم إنشاؤها حديثًا.
import { setMaxListeners, EventEmitter } from 'node:events';
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);const {
setMaxListeners,
EventEmitter,
} = require('node:events');
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);events.addAbortListener(signal, listener)
أضيف في: v20.5.0, v18.18.0
[مستقر: 1 - تجريبي]
مستقر: 1 الاستقرار: 1 - تجريبي
signal<AbortSignal>listener<Function> | <EventListener>- إرجاع: <Disposable> كائن
Disposableيزيل مستمعabort.
يستمع مرة واحدة إلى حدث abort على signal المقدم.
الاستماع إلى حدث abort على إشارات الإجهاض غير آمن وقد يؤدي إلى تسرب الموارد حيث يمكن لطرف ثالث آخر لديه الإشارة استدعاء e.stopImmediatePropagation(). لسوء الحظ، لا يمكن لـ Node.js تغيير ذلك لأنه سينتهك معيار الويب. بالإضافة إلى ذلك، تسهل واجهة برمجة التطبيقات الأصلية نسيان إزالة المستمعين.
تسمح واجهة برمجة التطبيقات هذه باستخدام AbortSignals بأمان في واجهات برمجة تطبيقات Node.js عن طريق حل هاتين المشكلتين من خلال الاستماع إلى الحدث بحيث لا يمنع stopImmediatePropagation المستمع من التشغيل.
إرجاع كائن يمكن التخلص منه بحيث يمكن إلغاء الاشتراك فيه بسهولة أكبر.
const { addAbortListener } = require('node:events');
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}import { addAbortListener } from 'node:events';
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}الصنف: events.EventEmitterAsyncResource extends EventEmitter
أُضيف في: الإصدار 17.4.0، 16.14.0
يدمج EventEmitter مع <AsyncResource> لـ EventEmitter التي تتطلب تتبعًا غير متزامن يدويًا. على وجه التحديد، ستعمل جميع الأحداث التي تنبعث من مثيلات events.EventEmitterAsyncResource داخل سياقها غير المتزامن.
import { EventEmitterAsyncResource, EventEmitter } from 'node:events';
import { notStrictEqual, strictEqual } from 'node:assert';
import { executionAsyncId, triggerAsyncId } from 'node:async_hooks';
// ستحدد أدوات التتبع غير المتزامن هذا على أنه 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// سيتم تشغيل مستمعي 'foo' في سياق EventEmitter غير المتزامن.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId);
strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});
const ee2 = new EventEmitter();
// مستمعو 'foo' على EventEmitters العادية التي لا تتعقب السياق غير المتزامن،
// ومع ذلك، يتم تشغيلها في نفس السياق غير المتزامن مثل emit().
ee2.on('foo', () => {
notStrictEqual(executionAsyncId(), ee2.asyncId);
notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});
Promise.resolve().then(() => {
ee1.emit('foo');
ee2.emit('foo');
});const { EventEmitterAsyncResource, EventEmitter } = require('node:events');
const { notStrictEqual, strictEqual } = require('node:assert');
const { executionAsyncId, triggerAsyncId } = require('node:async_hooks');
// ستحدد أدوات التتبع غير المتزامن هذا على أنه 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// سيتم تشغيل مستمعي 'foo' في سياق EventEmitter غير المتزامن.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId);
strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});
const ee2 = new EventEmitter();
// مستمعو 'foo' على EventEmitters العادية التي لا تتعقب السياق غير المتزامن،
// ومع ذلك، يتم تشغيلها في نفس السياق غير المتزامن مثل emit().
ee2.on('foo', () => {
notStrictEqual(executionAsyncId(), ee2.asyncId);
notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});
Promise.resolve().then(() => {
ee1.emit('foo');
ee2.emit('foo');
});يحتوي الصنف EventEmitterAsyncResource على نفس الطرق ويأخذ نفس الخيارات مثل EventEmitter و AsyncResource أنفسهم.
new events.EventEmitterAsyncResource([options])
options<Object>captureRejections<boolean> تُمكِّن التقاط رفض الوعد تلقائيًا. الافتراضي: false.name<string> نوع الحدث غير المتزامن. الافتراضي: new.target.name.triggerAsyncId<number> مُعرّف سياق التنفيذ الذي أنشأ هذا الحدث غير المتزامن. الافتراضي: executionAsyncId().requireManualDestroy<boolean> إذا تم تعيينه علىtrue، فسيتم تعطيلemitDestroyعند جمع الكائن المهمل. لا تحتاج عادةً إلى تعيين هذا (حتى إذا تم استدعاءemitDestroyيدويًا)، إلا إذا تم استردادasyncIdللمورد وتم استدعاءemitDestroyالخاصة بـ API الحساسة بواسطته. عند تعيينه علىfalse، سيحدث استدعاءemitDestroyفي جمع البيانات المهملة فقط إذا كان هناك على الأقل خطافdestroyنشط واحد. الافتراضي: false.
eventemitterasyncresource.asyncId
- النوع: <number>
asyncIdالفريد المُعيَّن للمورد.
eventemitterasyncresource.asyncResource
- النوع: <AsyncResource> الأساسي.
يحتوي كائن AsyncResource المُرجَع على خاصية eventEmitter إضافية توفر مرجعًا إلى EventEmitterAsyncResource.
eventemitterasyncresource.emitDestroy()
استدعاء جميع خطافات destroy. يجب استدعاء هذا مرة واحدة فقط. سيتم طرح خطأ إذا تم استدعاؤه أكثر من مرة. يجب استدعاء هذا يدويًا. إذا تُرك المورد ليتم جمعه بواسطة GC، فلن يتم استدعاء خطافات destroy أبدًا.
eventemitterasyncresource.triggerAsyncId
- النوع: <number> نفس
triggerAsyncIdالذي يتم تمريره إلى مُنشئAsyncResource.
واجهة برمجة تطبيقات EventTarget و Event
[السجل]
| الإصدار | التغييرات |
|---|---|
| v16.0.0 | تم تغيير معالجة أخطاء EventTarget. |
| v15.4.0 | لم يعد تجريبيًا. |
| v15.0.0 | أصبحت الفئات EventTarget و Event متاحة الآن كمتغيرات عالمية. |
| v14.5.0 | تمت إضافته في: v14.5.0 |
الكائنات EventTarget و Event هي تطبيق خاص بـ Node.js لـ EventTarget Web API الذي تعرضه بعض واجهات برمجة التطبيقات الأساسية في Node.js.
const target = new EventTarget();
target.addEventListener('foo', (event) => {
console.log('foo event happened!');
});EventTarget في Node.js مقابل EventTarget في DOM
هناك اختلافان رئيسيان بين EventTarget في Node.js و EventTarget Web API:
NodeEventTarget مقابل EventEmitter
يطبق الكائن NodeEventTarget مجموعة فرعية معدلة من واجهة برمجة تطبيقات EventEmitter التي تسمح له بمحاكاة EventEmitter عن كثب في مواقف معينة. NodeEventTarget ليس مثيلاً لـ EventEmitter ولا يمكن استخدامه بدلاً من EventEmitter في معظم الحالات.
مستمع الحدث
يمكن أن يكون مستمعو الأحداث المسجلين لنوع حدث type إما وظائف JavaScript أو كائنات لها خاصية handleEvent قيمتها عبارة عن دالة.
في كلتا الحالتين، يتم استدعاء دالة المعالج مع وسيط event الذي تم تمريره إلى الدالة eventTarget.dispatchEvent().
يمكن استخدام الدوال غير المتزامنة كمستمعين للأحداث. إذا تم رفض دالة معالج غير متزامنة، فسيتم التقاط الرفض ومعالجته كما هو موضح في EventTarget error handling.
لا يمنع الخطأ الذي يتم طرحه بواسطة دالة معالج واحدة استدعاء المعالجات الأخرى.
يتم تجاهل القيمة المرجعة لدالة المعالج.
يتم استدعاء المعالجات دائمًا بالترتيب الذي تمت إضافتها به.
قد تقوم دوال المعالجات بتغيير كائن event.
function handler1(event) {
console.log(event.type); // يطبع 'foo'
event.a = 1;
}
async function handler2(event) {
console.log(event.type); // يطبع 'foo'
console.log(event.a); // يطبع 1
}
const handler3 = {
handleEvent(event) {
console.log(event.type); // يطبع 'foo'
},
};
const handler4 = {
async handleEvent(event) {
console.log(event.type); // يطبع 'foo'
},
};
const target = new EventTarget();
target.addEventListener('foo', handler1);
target.addEventListener('foo', handler2);
target.addEventListener('foo', handler3);
target.addEventListener('foo', handler4, { once: true });معالجة أخطاء EventTarget
عندما يطرح مستمع حدث مسجل (أو يعيد Promise يرفض)، بشكل افتراضي، يتم التعامل مع الخطأ على أنه استثناء غير معالج في process.nextTick(). هذا يعني أن الاستثناءات غير المعالجة في EventTarget ستنهي عملية Node.js افتراضيًا.
الطرح داخل مستمع الحدث لن يوقف معالجات أخرى مسجلة من الاستدعاء.
لا تنفذ EventTarget أي معالجة افتراضية خاصة للأحداث من النوع 'error' مثل EventEmitter.
حاليًا، يتم توجيه الأخطاء أولاً إلى حدث process.on('error') قبل الوصول إلى process.on('uncaughtException'). هذا السلوك مهمل وسيتغير في إصدار مستقبلي لمواءمة EventTarget مع واجهات برمجة تطبيقات Node.js الأخرى. يجب مواءمة أي كود يعتمد على حدث process.on('error') مع السلوك الجديد.
الصنف: Event
[سجل التغييرات]
| الإصدار | التغييرات |
|---|---|
| v15.0.0 | يتوفر الآن الصنف Event من خلال الكائن العام. |
| v14.5.0 | تمت إضافته في: v14.5.0 |
كائن Event هو تكييف لـ Event Web API. يتم إنشاء المثيلات داخليًا بواسطة Node.js.
event.bubbles
تمت إضافته في: v14.5.0
- النوع: <boolean> يُرجع دائمًا
false.
لا يتم استخدام هذا في Node.js ويتم توفيره فقط من أجل الاكتمال.
event.cancelBubble
تمت إضافته في: v14.5.0
[مستقر: 3 - قديم]
مستقر: 3 الاستقرار: 3 - قديم: استخدم event.stopPropagation() بدلاً من ذلك.
- النوع: <boolean>
اسم بديل لـ event.stopPropagation() إذا تم تعيينه على true. لا يتم استخدام هذا في Node.js ويتم توفيره فقط من أجل الاكتمال.
event.cancelable
تمت إضافته في: v14.5.0
- النوع: <boolean> True إذا تم إنشاء الحدث مع خيار
cancelable.
event.composed
أُضيف في: الإصدار 14.5.0
- النوع: <boolean> يُرجع دائمًا
false.
هذا غير مستخدم في Node.js ويتم توفيره فقط من أجل الاكتمال.
event.composedPath()
أُضيف في: الإصدار 14.5.0
يُرجع مصفوفة تحتوي على EventTarget الحالي كإدخال وحيد أو فارغ إذا لم يتم إرسال الحدث. هذا غير مستخدم في Node.js ويتم توفيره فقط من أجل الاكتمال.
event.currentTarget
أُضيف في: الإصدار 14.5.0
- النوع: <EventTarget>
EventTargetالذي يُرسل الحدث.
اسم بديل لـ event.target.
event.defaultPrevented
أُضيف في: الإصدار 14.5.0
- النوع: <boolean>
يكون true إذا كان cancelable هو true وتم استدعاء event.preventDefault().
event.eventPhase
أُضيف في: الإصدار 14.5.0
- النوع: <number> يُرجع
0بينما لا يتم إرسال الحدث، و2أثناء إرساله.
هذا غير مستخدم في Node.js ويتم توفيره فقط من أجل الاكتمال.
event.initEvent(type[, bubbles[, cancelable]])
أُضيف في: الإصدار 19.5.0
[مستقر: 3 - قديم]
مستقر: 3 الاستقرار: 3 - قديم: تعتبره مواصفات WHATWG مهملًا ولا ينبغي للمستخدمين استخدامه على الإطلاق.
زائد عن الحاجة مع مُنشئات الأحداث وغير قادر على تعيين composed. هذا غير مستخدم في Node.js ويتم توفيره فقط من أجل الاكتمال.
event.isTrusted
أُضيف في: الإصدار 14.5.0
- النوع: <boolean>
يتم إصدار حدث <AbortSignal> "abort" مع تعيين isTrusted على true. القيمة هي false في جميع الحالات الأخرى.
event.preventDefault()
أُضيف في: v14.5.0
يُعيّن الخاصية defaultPrevented إلى true إذا كانت cancelable هي true.
event.returnValue
أُضيف في: v14.5.0
[مستقر: 3 - قديم]
مستقر: 3 الاستقرار: 3 - قديم: استخدم event.defaultPrevented بدلاً من ذلك.
- النوع: <boolean> صحيح إذا لم يتم إلغاء الحدث.
قيمة event.returnValue هي دائمًا عكس event.defaultPrevented. لا يتم استخدام هذا في Node.js ويتم توفيره فقط للإكمال.
event.srcElement
أُضيف في: v14.5.0
[مستقر: 3 - قديم]
مستقر: 3 الاستقرار: 3 - قديم: استخدم event.target بدلاً من ذلك.
- النوع: <EventTarget>
EventTargetالذي يرسل الحدث.
اسم بديل لـ event.target.
event.stopImmediatePropagation()
أُضيف في: v14.5.0
يوقف استدعاء مستمعي الأحداث بعد اكتمال المستمع الحالي.
event.stopPropagation()
أُضيف في: v14.5.0
لا يتم استخدام هذا في Node.js ويتم توفيره فقط للإكمال.
event.target
أُضيف في: v14.5.0
- النوع: <EventTarget>
EventTargetالذي يرسل الحدث.
event.timeStamp
أُضيف في: v14.5.0
- النوع: <number>
الطابع الزمني بالمللي ثانية عند إنشاء كائن Event.
event.type
أُضيف في: v14.5.0
- النوع: <string>
معرف نوع الحدث.
الصنف: EventTarget
[التاريخ]
| الإصدار | التغييرات |
|---|---|
| v15.0.0 | يتوفر الآن الصنف EventTarget من خلال الكائن العام. |
| v14.5.0 | أُضيف في: v14.5.0 |
eventTarget.addEventListener(type, listener[, options])
[سجل التغييرات]
| الإصدار | التغييرات |
|---|---|
| v15.4.0 | إضافة دعم خيار signal. |
| v14.5.0 | تمت الإضافة في: v14.5.0 |
type<string>listener<Function> | <EventListener>options<Object>once<boolean> عندما تكونtrue، تتم إزالة المستمع تلقائيًا عند استدعائه لأول مرة. الافتراضي:false.passive<boolean> عندما تكونtrue، تعمل كتلميح على أن المستمع لن يستدعي طريقةpreventDefault()الخاصة بكائنEvent. الافتراضي:false.capture<boolean> لا تستخدم مباشرة من قبل Node.js. تمت إضافتها من أجل اكتمال API. الافتراضي:false.signal<AbortSignal> ستتم إزالة المستمع عند استدعاء طريقةabort()لكائن AbortSignal المحدد.
يضيف معالجًا جديدًا لحدث type. تتم إضافة أي listener معين مرة واحدة فقط لكل type ولكل قيمة خيار capture.
إذا كان خيار once هو true، تتم إزالة listener بعد المرة التالية التي يتم فيها إرسال حدث type.
لا يتم استخدام خيار capture بواسطة Node.js بأي طريقة وظيفية بخلاف تتبع مستمعي الأحداث المسجلين وفقًا لمواصفات EventTarget. على وجه التحديد، يتم استخدام خيار capture كجزء من المفتاح عند تسجيل listener. يمكن إضافة أي listener فردي مرة واحدة مع capture = false، ومرة واحدة مع capture = true.
function handler(event) {}
const target = new EventTarget();
target.addEventListener('foo', handler, { capture: true }); // first
target.addEventListener('foo', handler, { capture: false }); // second
// Removes the second instance of handler
target.removeEventListener('foo', handler);
// Removes the first instance of handler
target.removeEventListener('foo', handler, { capture: true });eventTarget.dispatchEvent(event)
أضيف في: v14.5.0
event<Event>- إرجاع: <boolean>
trueإذا كانت قيمة سمةcancelableللحدث خاطئة أو لم يتم استدعاء طريقةpreventDefault()الخاصة به، وإلاfalse.
يقوم بإرسال event إلى قائمة معالجات event.type.
يتم استدعاء مستمعي الأحداث المسجلين بشكل متزامن بالترتيب الذي تم تسجيلهم به.
eventTarget.removeEventListener(type, listener[, options])
أضيف في: v14.5.0
type<string>listener<Function> | <EventListener>options<Object>capture<boolean>
يزيل listener من قائمة معالجات الحدث type.
الصنف: CustomEvent
[سجل التعديلات]
| الإصدار | التغييرات |
|---|---|
| v23.0.0 | لم تعد تجريبية. |
| v22.1.0, v20.13.0 | CustomEvent الآن مستقرة. |
| v19.0.0 | لم تعد خلف علامة سطر الأوامر --experimental-global-customevent. |
| v18.7.0, v16.17.0 | أضيفت في: v18.7.0, v16.17.0 |
[مستقر: 2 - مستقر]
مستقر: 2 الاستقرار: 2 - مستقر
- يمتد: <Event>
الكائن CustomEvent هو تكييف لـ CustomEvent Web API. يتم إنشاء المثيلات داخليًا بواسطة Node.js.
event.detail
[سجل التعديلات]
| الإصدار | التغييرات |
|---|---|
| v22.1.0, v20.13.0 | CustomEvent الآن مستقرة. |
| v18.7.0, v16.17.0 | أضيفت في: v18.7.0, v16.17.0 |
[مستقر: 2 - مستقر]
مستقر: 2 الاستقرار: 2 - مستقر
- النوع: <any> إرجاع بيانات مخصصة تم تمريرها عند التهيئة.
للقراءة فقط.
الفئة: NodeEventTarget
أضيف في: الإصدار v14.5.0
- يمتد: <EventTarget>
إن NodeEventTarget هو امتداد خاص بـ Node.js لـ EventTarget يحاكي مجموعة فرعية من واجهة برمجة تطبيقات EventEmitter.
nodeEventTarget.addListener(type, listener)
أضيف في: الإصدار v14.5.0
type<string>listener<Function> | <EventListener>- الإرجاع: <EventTarget> هذا
امتداد خاص بـ Node.js للفئة EventTarget يحاكي واجهة برمجة تطبيقات EventEmitter المكافئة. الفرق الوحيد بين addListener() و addEventListener() هو أن addListener() ستعيد مرجعًا إلى EventTarget.
nodeEventTarget.emit(type, arg)
أضيف في: الإصدار v15.2.0
type<string>arg<any>- الإرجاع: <boolean>
trueإذا كانت مستمعي الأحداث المسجلين لـtypeموجودين، وإلاfalse.
امتداد خاص بـ Node.js للفئة EventTarget يقوم بتوزيع arg إلى قائمة المعالجات لـ type.
nodeEventTarget.eventNames()
أضيف في: الإصدار v14.5.0
- الإرجاع: <string[]>
امتداد خاص بـ Node.js للفئة EventTarget الذي يُرجع مصفوفة من أسماء type للأحداث التي تم تسجيل مستمعي الأحداث لها.
nodeEventTarget.listenerCount(type)
أضيف في: الإصدار v14.5.0
امتداد خاص بـ Node.js للفئة EventTarget الذي يُرجع عدد مستمعي الأحداث المسجلين لـ type.
nodeEventTarget.setMaxListeners(n)
تمت إضافتها في: v14.5.0
n<number>
امتداد خاص بـ Node.js لفئة EventTarget التي تحدد عدد أقصى مستمعي الأحداث على أنه n.
nodeEventTarget.getMaxListeners()
تمت إضافتها في: v14.5.0
- الإرجاع: <number>
امتداد خاص بـ Node.js لفئة EventTarget التي تُرجع عدد أقصى مستمعي الأحداث.
nodeEventTarget.off(type, listener[, options])
تمت إضافتها في: v14.5.0
type<string>listener<Function> | <EventListener>options<Object>capture<boolean>
الإرجاع: <EventTarget> this
اسم مستعار خاص بـ Node.js لـ eventTarget.removeEventListener().
nodeEventTarget.on(type, listener)
تمت إضافتها في: v14.5.0
type<string>listener<Function> | <EventListener>- الإرجاع: <EventTarget> this
اسم مستعار خاص بـ Node.js لـ eventTarget.addEventListener().
nodeEventTarget.once(type, listener)
تمت إضافتها في: v14.5.0
type<string>listener<Function> | <EventListener>- الإرجاع: <EventTarget> this
امتداد خاص بـ Node.js لفئة EventTarget يضيف مستمع once لنوع الحدث المحدد type. هذا يعادل استدعاء on مع تعيين الخيار once على true.
nodeEventTarget.removeAllListeners([type])
أُضيف في: الإصدار v14.5.0
type<سلسلة نصية>- يعيد: <EventTarget> هذا
امتداد خاص بـ Node.js لفئة EventTarget. إذا تم تحديد type، فسيقوم بإزالة جميع المستمعين المسجلين لـ type، وإلا فإنه يزيل جميع المستمعين المسجلين.
nodeEventTarget.removeListener(type, listener[, options])
أُضيف في: الإصدار v14.5.0
type<سلسلة نصية>listener<دالة> | <EventListener>options<كائن>capture<قيمة منطقية>
يعيد: <EventTarget> هذا
امتداد خاص بـ Node.js لفئة EventTarget يقوم بإزالة listener لنوع type المحدد. الفرق الوحيد بين removeListener() و removeEventListener() هو أن removeListener() ستعيد مرجعًا إلى EventTarget.