Event Emitter
// 0. import event listeners
const { EventEmitter } = require('node:events');
class MyEmitter extends EventEmitter {}
// 1. creating event emitter
const eventEmitter = new EventEmitter();
const myEventEmitter = new MyEmitter();
// 3. listen event that I made
eventEmitter.on('connection', function(){
console.log('Connection Successful!');
});
myEventEmitter.on('greeting', function(){
console.log('Hello!');
});
// 2. firing custom event
eventEmitter.emit('connection');
myEventEmitter.emit('greeting');
// Connection Successful!
// Hello!
매개변수 전달 및 ES6
const { EventEmitter } = require('node:events');
class MyEmitter extends EventEmitter {}
const myEventEmitter = new MyEmitter();
const a = 1;
const b = 100;
myEventEmitter.on('greeting', function (arg1, arg2) {
console.log(this);
console.log(this === myEventEmitter);
console.log(`Result is... ${arg1 + arg2}`);
});
myEventEmitter.emit('greeting', a, b);
/*
--- logs ---
MyEmitter {
_events: [Object: null prototype] { greeting: [Function (anonymous)] },
_eventsCount: 1,
_maxListeners: undefined,
[Symbol(kCapture)]: false
}
true
Result is... 101
*/
커스텀 Emitter 객체에 이벤트를 등록할 때 인자를 전달할 수 있다.
인자는 이벤트 리스너로 전달되어 값으로 사용할 수 있다.
등록된 이벤트 리스너 함수는 Emitter 객체에서 생성된 메서드이기 때문에 this는 Emitter객체를 가르킨다. (this === myEventEmitter)
/* 생략 */
const a = 1;
const b = 100;
myEventEmitter.on('greeting', (arg1, arg2) => {
console.log(this);
console.log(this === myEventEmitter);
console.log(`Result is... ${arg1 + arg2}`);
});
myEventEmitter.emit('greeting', a, b);
/*
--- logs ---
{}
false
Result is... 101
*/
이벤트 리스너 전달 함수는 ES6의 arrow function을 사용할 수 있다.
하지만, arrow function의 특성상 this는 함수 내부 블록에 바인딩 되므로
this 사용시 주의해야한다.
동기와 비동기
/* 생략 */
const a = 1;
const b = 100;
myEventEmitter.on('greeting', (arg1, arg2) => {
setImmediate(() => {
console.log('this happens asynchronously on setImmediate');
});
process.nextTick(() => {
console.log('this happens asynchronously on nextTick');
});
console.log(arg1 + arg2);
});
/*
--- logs ---
101
this happens asynchronously on nextTick
this happens asynchronously on setImmediate
*/
Fire event
/* 생략 */
let count = 0;
myEventEmitter.on('greeting', () => {
count += 1;
console.log(count);
});
// firing custom event
myEventEmitter.emit('greeting'); // 1
myEventEmitter.emit('greeting'); // 2
myEventEmitter.emit('greeting'); // 3
Emitter 객체의 emit 메서드는 이벤트를 발동시키는 역할을 하여 실행시키는 만큼 등록된 커스텀 이벤트 리스너가 발동된다.
/* 생략 */
let count = 0;
myEventEmitter.once('greeting', () => {
count += 1;
console.log(count);
});
// firing custom event
myEventEmitter.emit('greeting'); // 1
myEventEmitter.emit('greeting'); // <-- 무시
myEventEmitter.emit('greeting'); // <-- 무시
이벤트의 발동횟수와 관계없이 한 번만 실행시켜야하는 경우라면 Emitter의 on 메서드 대신 once 메서드를 통해 콜백 함수를 등록시키면된다.
Emitter를 세번 발동시켰지만 실제도 동작한 것은 하나의 이벤트가 된다.
Error Events
/* 생략 */
myEventEmitter.on('error', (err) => {
console.error(err);
});
myEventEmitter.emit('error', new Error('에러 발생!!'));
// 에러 발생!!
// Error logs...