이벤트
소스 코드: lib/events.js
Node.js 코어 API의 상당 부분은 특정 종류의 객체("emitter"라고 함)가 이름이 지정된 이벤트를 방출하여 Function
객체("listener"라고 함)를 호출하는 관용적인 비동기 이벤트 기반 아키텍처를 기반으로 구축됩니다.
예를 들어 net.Server
객체는 피어가 연결될 때마다 이벤트를 방출하고, fs.ReadStream
은 파일이 열릴 때 이벤트를 방출하며, 스트림은 읽을 수 있는 데이터가 있을 때마다 이벤트를 방출합니다.
이벤트를 방출하는 모든 객체는 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('an event occurred!')
})
myEmitter.emit('event')
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', () => {
console.log('an event occurred!')
})
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)
// Prints:
// 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)
// Prints:
// 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)
// Prints: a b undefined
})
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)
// Prints: 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: 2
const 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')
// Ignored
const 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'
이벤트가 발생하면 에러가 throw되고, 스택 추적이 출력되며 Node.js 프로세스가 종료됩니다.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('whoops!'))
// Node.js를 throw하고 충돌시킴
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('whoops!'))
// Node.js를 throw하고 충돌시킴
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 error
const 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
events.errorMonitor
심볼을 사용하여 리스너를 설치하여 발생된 에러를 소비하지 않고 'error'
이벤트를 모니터링할 수 있습니다.
import { EventEmitter, errorMonitor } from 'node:events'
const myEmitter = new EventEmitter()
myEmitter.on(errorMonitor, err => {
MyMonitoringTool.log(err)
})
myEmitter.emit('error', new Error('whoops!'))
// 여전히 Node.js를 throw하고 충돌시킴
const { EventEmitter, errorMonitor } = require('node:events')
const myEmitter = new EventEmitter()
myEmitter.on(errorMonitor, err => {
MyMonitoringTool.log(err)
})
myEmitter.emit('error', new Error('whoops!'))
// 여전히 Node.js를 throw하고 충돌시킴
Promise 거부 캡처
이벤트 핸들러에서 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')
})
EventEmitter
생성자의 captureRejections
옵션 또는 전역 설정을 사용하면 이 동작이 변경됩니다. Promise
에 .then(undefined, handler)
핸들러를 설치하여 예외를 비동기적으로 라우팅합니다. 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)
captureRejections
동작에 의해 생성된 'error'
이벤트에는 무한 오류 루프를 방지하기 위한 catch 핸들러가 없습니다. 'error'
이벤트 핸들러로 async
함수를 사용하지 않는 것이 좋습니다.
클래스: 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')
모든 EventEmitter
는 새로운 리스너가 추가될 때 'newListener'
이벤트를, 기존 리스너가 제거될 때 'removeListener'
이벤트를 방출합니다.
다음 옵션을 지원합니다.
captureRejections
<boolean> Promise reject 자동 캡처를 활성화합니다. 기본값:false
.
이벤트: 'newListener'
추가됨: v0.1.26
eventName
<string> | <symbol> 수신 대기 중인 이벤트의 이름listener
<Function> 이벤트 핸들러 함수
EventEmitter
인스턴스는 리스너가 내부 리스너 배열에 추가되기 전에 자체 'newListener'
이벤트를 방출합니다.
'newListener'
이벤트에 등록된 리스너에는 이벤트 이름과 추가될 리스너에 대한 참조가 전달됩니다.
이벤트가 리스너를 추가하기 전에 트리거된다는 사실은 미묘하지만 중요한 부작용이 있습니다. 'newListener'
콜백 내에서 동일한 name
에 등록된 추가 리스너는 추가되고 있는 리스너 앞에 삽입됩니다.
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
// A
const 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 |
'removeListener'
이벤트는 listener
가 제거된 후에 발생합니다.
emitter.addListener(eventName, listener)
추가됨: v0.1.26
emitter.on(eventName, listener)
의 별칭입니다.
emitter.emit(eventName[, ...args])
추가됨: v0.1.26
eventName
으로 명명된 이벤트에 대해 등록된 각 리스너를 등록된 순서대로 동기적으로 호출하고, 각 리스너에 제공된 인수를 전달합니다.
이벤트에 리스너가 있으면 true
를, 그렇지 않으면 false
를 반환합니다.
import { EventEmitter } from 'node:events'
const myEmitter = new EventEmitter()
// 첫 번째 리스너
myEmitter.on('event', function firstListener() {
console.log('Helloooo! 첫 번째 리스너')
})
// 두 번째 리스너
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`매개변수가 있는 이벤트 ${arg1}, ${arg2} 두 번째 리스너에서`)
})
// 세 번째 리스너
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ')
console.log(`매개변수가 있는 이벤트 ${parameters} 세 번째 리스너에서`)
})
console.log(myEmitter.listeners('event'))
myEmitter.emit('event', 1, 2, 3, 4, 5)
// 출력:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! 첫 번째 리스너
// 매개변수가 있는 이벤트 1, 2 두 번째 리스너에서
// 매개변수가 있는 이벤트 1, 2, 3, 4, 5 세 번째 리스너에서
const EventEmitter = require('node:events')
const myEmitter = new EventEmitter()
// 첫 번째 리스너
myEmitter.on('event', function firstListener() {
console.log('Helloooo! 첫 번째 리스너')
})
// 두 번째 리스너
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`매개변수가 있는 이벤트 ${arg1}, ${arg2} 두 번째 리스너에서`)
})
// 세 번째 리스너
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ')
console.log(`매개변수가 있는 이벤트 ${parameters} 세 번째 리스너에서`)
})
console.log(myEmitter.listeners('event'))
myEmitter.emit('event', 1, 2, 3, 4, 5)
// 출력:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! 첫 번째 리스너
// 매개변수가 있는 이벤트 1, 2 두 번째 리스너에서
// 매개변수가 있는 이벤트 1, 2, 3, 4, 5 세 번째 리스너에서
emitter.eventNames()
추가됨: v6.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())
// 출력: [ '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())
// 출력: [ 'foo', 'bar', Symbol(symbol) ]
emitter.getMaxListeners()
추가됨: v1.0.0
- 반환값: <integer>
EventEmitter
에 대한 현재 최대 리스너 값을 반환합니다. 이 값은 emitter.setMaxListeners(n)
으로 설정하거나 events.defaultMaxListeners
의 기본값을 사용합니다.
emitter.listenerCount(eventName[, listener])
[히스토리]
버전 | 변경 사항 |
---|---|
v19.8.0, v18.16.0 | listener 인수 추가 |
v3.2.0 | 추가됨: v3.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')))
// 출력: [ [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>
eventName
으로 명명된 이벤트에 대한 리스너 배열의 끝에 listener
함수를 추가합니다. 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')
// 출력:
// b
// a
const EventEmitter = require('node:events')
const myEE = new EventEmitter()
myEE.on('foo', () => console.log('a'))
myEE.prependListener('foo', () => console.log('b'))
myEE.emit('foo')
// 출력:
// b
// a
emitter.once(eventName, listener)
추가됨: v0.3.0
eventName
<string> | <symbol> 이벤트 이름입니다.listener
<Function> 콜백 함수입니다.- 반환값: <EventEmitter>
eventName
으로 명명된 이벤트에 대한 일회성 listener
함수를 추가합니다. 다음 번에 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')
// 출력:
// b
// a
const EventEmitter = require('node:events')
const myEE = new EventEmitter()
myEE.once('foo', () => console.log('a'))
myEE.prependOnceListener('foo', () => console.log('b'))
myEE.emit('foo')
// 출력:
// b
// a
emitter.prependListener(eventName, listener)
추가됨: v6.0.0
eventName
<string> | <symbol> 이벤트 이름입니다.listener
<Function> 콜백 함수입니다.- 반환값: <EventEmitter>
eventName
으로 명명된 이벤트의 리스너 배열의 처음에 listener
함수를 추가합니다. listener
가 이미 추가되었는지 확인하는 검사는 수행되지 않습니다. eventName
과 listener
의 동일한 조합을 여러 번 전달하는 여러 호출은 listener
가 여러 번 추가되고 호출되는 결과를 초래합니다.
server.prependListener('connection', stream => {
console.log('someone connected!')
})
EventEmitter
에 대한 참조를 반환하므로 호출을 연결할 수 있습니다.
emitter.prependOnceListener(eventName, listener)
추가됨: v6.0.0
eventName
<string> | <symbol> 이벤트 이름입니다.listener
<Function> 콜백 함수입니다.- 반환값: <EventEmitter>
eventName
으로 명명된 이벤트에 대한 일회성 listener
함수를 listener 배열의 맨 앞에 추가합니다. 다음 번에 eventName
이 트리거되면 이 listener는 제거된 후 호출됩니다.
server.prependOnceListener('connection', stream => {
console.log('Ah, we have our first user!')
})
EventEmitter
에 대한 참조를 반환하므로 호출을 체이닝할 수 있습니다.
emitter.removeAllListeners([eventName])
추가됨: v0.1.26
eventName
<string> | <symbol>- 반환값: <EventEmitter>
모든 listener 또는 지정된 eventName
의 listener를 제거합니다.
다른 곳의 코드에 추가된 listener를 제거하는 것은 좋지 않은 방법이며, 특히 EventEmitter
인스턴스가 다른 구성 요소 또는 모듈(예: 소켓 또는 파일 스트림)에 의해 생성된 경우 더욱 그렇습니다.
EventEmitter
에 대한 참조를 반환하므로 호출을 체이닝할 수 있습니다.
emitter.removeListener(eventName, listener)
추가됨: v0.1.26
eventName
<string> | <symbol>listener
<Function>- 반환값: <EventEmitter>
eventName
으로 명명된 이벤트의 listener 배열에서 지정된 listener
를 제거합니다.
const callback = stream => {
console.log('someone connected!')
}
server.on('connection', callback)
// ...
server.removeListener('connection', callback)
removeListener()
는 listener 배열에서 listener의 인스턴스를 최대 하나만 제거합니다. 지정된 eventName
에 대해 단일 listener가 listener 배열에 여러 번 추가된 경우 removeListener()
를 여러 번 호출하여 각 인스턴스를 제거해야 합니다.
이벤트가 발생하면 발생 시점에 연결된 모든 listener가 순서대로 호출됩니다. 이는 발생 후 마지막 listener 실행 전에 수행되는 removeListener()
또는 removeAllListeners()
호출은 진행 중인 emit()
에서 해당 listener를 제거하지 않는다는 것을 의미합니다. 후속 이벤트는 예상대로 동작합니다.
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:
// A
const 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
listener는 내부 배열을 사용하여 관리되므로 이를 호출하면 제거되는 listener 후에 등록된 모든 listener의 위치 색인이 변경됩니다. 이는 listener가 호출되는 순서에는 영향을 미치지 않지만 emitter.listeners()
메서드에서 반환된 listener 배열의 복사본을 다시 생성해야 함을 의미합니다.
단일 함수가 단일 이벤트에 대한 처리기로 여러 번 추가된 경우(아래 예와 같이), removeListener()
는 가장 최근에 추가된 인스턴스를 제거합니다. 예에서 once('ping')
listener가 제거됩니다.
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
<정수>- 반환값: <EventEmitter>
기본적으로 EventEmitter
는 특정 이벤트에 10개 이상의 리스너가 추가되면 경고를 출력합니다. 이는 메모리 누수를 찾는 데 도움이 되는 유용한 기본값입니다. emitter.setMaxListeners()
메서드를 사용하면 이 특정 EventEmitter
인스턴스에 대한 제한을 수정할 수 있습니다. 무제한의 리스너 수를 나타내려면 값을 Infinity
(또는 0
)로 설정할 수 있습니다.
EventEmitter
에 대한 참조를 반환하므로 호출을 체이닝할 수 있습니다.
emitter.rawListeners(eventName)
추가됨: v9.4.0
eventName
<문자열> | <심볼>- 반환값: <Function[]>
eventName
으로 지정된 이벤트에 대한 리스너 배열의 복사본을 반환합니다. .once()
에 의해 생성된 것과 같은 모든 래퍼를 포함합니다.
import { EventEmitter } from 'node:events'
const emitter = new EventEmitter()
emitter.once('log', () => console.log('log once'))
// 위에서 바인딩된 원래 리스너를 포함하는 속성 `listener`를 가진 함수 `onceWrapper`를 포함하는 새 배열을 반환합니다.
const listeners = emitter.rawListeners('log')
const logFnWrapper = listeners[0]
// 콘솔에 "log once"를 기록하고 `once` 이벤트를 언바인딩하지 않습니다.
logFnWrapper.listener()
// 콘솔에 "log once"를 기록하고 리스너를 제거합니다.
logFnWrapper()
emitter.on('log', () => console.log('log persistently'))
// 위에서 `.on()`에 의해 바인딩된 단일 함수를 포함하는 새 배열을 반환합니다.
const newListeners = emitter.rawListeners('log')
// "log persistently"를 두 번 기록합니다.
newListeners[0]()
emitter.emit('log')
const EventEmitter = require('node:events')
const emitter = new EventEmitter()
emitter.once('log', () => console.log('log once'))
// 위에서 바인딩된 원래 리스너를 포함하는 속성 `listener`를 가진 함수 `onceWrapper`를 포함하는 새 배열을 반환합니다.
const listeners = emitter.rawListeners('log')
const logFnWrapper = listeners[0]
// 콘솔에 "log once"를 기록하고 `once` 이벤트를 언바인딩하지 않습니다.
logFnWrapper.listener()
// 콘솔에 "log once"를 기록하고 리스너를 제거합니다.
logFnWrapper()
emitter.on('log', () => console.log('log persistently'))
// 위에서 `.on()`에 의해 바인딩된 단일 함수를 포함하는 새 배열을 반환합니다.
const newListeners = emitter.rawListeners('log')
// "log persistently"를 두 번 기록합니다.
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 |
이벤트를 방출할 때 Promise 거부가 발생하고 이미터에서 captureRejections
가 활성화된 경우 Symbol.for('nodejs.rejection')
메서드가 호출됩니다. Symbol.for('nodejs.rejection')
대신 events.captureRejectionSymbol
을 사용할 수 있습니다.
import { EventEmitter, captureRejectionSymbol } from 'node:events'
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true })
}
[captureRejectionSymbol](err, event, ...args) {
console.log('rejection happened for', event, 'with', 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('rejection happened for', event, 'with', err, ...args)
this.destroy(err)
}
destroy(err) {
// 여기서 리소스를 해제합니다.
}
}
events.defaultMaxListeners
추가됨: v0.11.2
기본적으로 단일 이벤트에 대해 최대 10
개의 리스너를 등록할 수 있습니다. emitter.setMaxListeners(n)
메서드를 사용하여 개별 EventEmitter
인스턴스에 대한 이 한도를 변경할 수 있습니다. 모든 EventEmitter
인스턴스의 기본값을 변경하려면 events.defaultMaxListeners
속성을 사용할 수 있습니다. 이 값이 양수가 아니면 RangeError
가 발생합니다.
events.defaultMaxListeners
를 설정할 때는 변경 사항이 변경되기 전에 생성된 인스턴스를 포함하여 모든 EventEmitter
인스턴스에 영향을 미치므로 주의해야 합니다. 그러나 emitter.setMaxListeners(n)
을 호출하면 여전히 events.defaultMaxListeners
보다 우선합니다.
이는 절대적인 한계가 아닙니다. EventEmitter
인스턴스는 더 많은 리스너를 추가할 수 있지만 "가능한 EventEmitter 메모리 누수"가 감지되었음을 나타내는 추적 경고를 stderr에 출력합니다. 단일 EventEmitter
에 대해 emitter.getMaxListeners()
및 emitter.setMaxListeners()
메서드를 사용하여 이 경고를 일시적으로 방지할 수 있습니다.
defaultMaxListeners
는 AbortSignal
인스턴스에는 영향을 미치지 않습니다. 개별 AbortSignal
인스턴스에 대한 경고 제한을 설정하기 위해 emitter.setMaxListeners(n)
을 사용하는 것은 여전히 가능하지만, 기본적으로 AbortSignal
인스턴스는 경고하지 않습니다.
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
으로 지정된 이벤트에 대한 리스너 배열의 복사본을 반환합니다.
EventEmitter
의 경우 이것은 이미터에서 .listeners
를 호출하는 것과 정확히 동일하게 동작합니다.
EventTarget
의 경우 이벤트 대상에 대한 이벤트 리스너를 가져오는 유일한 방법입니다. 이는 디버깅 및 진단 목적으로 유용합니다.
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>
EventEmitter
가 지정된 이벤트를 방출할 때 또는 대기 중에 EventEmitter
가 'error'
를 방출할 때 거부되는 Promise
를 생성합니다. Promise
는 지정된 이벤트에 방출된 모든 인수의 배열로 확인됩니다.
이 메서드는 의도적으로 일반적이며, 특별한 'error'
이벤트 의미 체계가 없고 'error'
이벤트를 수신하지 않는 웹 플랫폼 EventTarget 인터페이스와 함께 작동합니다.
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 boom
const { 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()
에서 방출되는 여러 이벤트 대기
process.nextTick()
작업의 동일한 배치에서 또는 여러 이벤트가 동기적으로 방출될 때마다 여러 이벤트를 기다리기 위해 events.once()
함수를 사용할 때 주목할 만한 예외 사례가 있습니다. 특히, 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')
// 이 Promise는 'foo' 이벤트가 Promise가 생성되기 전에 이미 방출되었기 때문에 해결되지 않습니다.
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')
// 이 Promise는 'foo' 이벤트가 Promise가 생성되기 전에 이미 방출되었기 때문에 해결되지 않습니다.
await once(myEE, 'foo')
console.log('foo')
}
process.nextTick(() => {
myEE.emit('bar')
myEE.emit('foo')
})
foo().then(() => console.log('done'))
두 이벤트 모두를 잡으려면 각 Promise를 대기하기 전에 생성한 다음 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>
모든 새로운 EventEmitter
객체에 대한 기본 captureRejections
옵션을 변경합니다.
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> 이벤트 이름
주어진 emitter
에 등록된 주어진 eventName
에 대한 수신기 수를 반환하는 클래스 메서드입니다.
import { EventEmitter, listenerCount } from 'node:events'
const myEmitter = new EventEmitter()
myEmitter.on('event', () => {})
myEmitter.on('event', () => {})
console.log(listenerCount(myEmitter, 'event'))
// 출력: 2
const { EventEmitter, listenerCount } = require('node:events')
const myEmitter = new EventEmitter()
myEmitter.on('event', () => {})
myEmitter.on('event', () => {})
console.log(listenerCount(myEmitter, 'event'))
// 출력: 2
events.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>options
<Object>signal
<AbortSignal> 대기 중인 이벤트를 취소하는 데 사용할 수 있습니다.close
- <string[]> 반복을 종료할 이벤트의 이름.highWaterMark
- <integer> 기본값:Number.MAX_SAFE_INTEGER
상한선. 버퍼링되는 이벤트의 크기가 이보다 클 때마다 이벤트 방출기가 일시 중지됩니다.pause()
및resume()
메서드를 구현하는 이벤트 방출기에서만 지원됩니다.lowWaterMark
- <integer> 기본값:1
하한선. 버퍼링되는 이벤트의 크기가 이보다 작을 때마다 이벤트 방출기가 다시 시작됩니다.pause()
및resume()
메서드를 구현하는 이벤트 방출기에서만 지원됩니다.
반환값:
emitter
에서 방출된eventName
이벤트를 반복하는 <AsyncIterator>
import { on, EventEmitter } from 'node:events'
import process from 'node:process'
const ee = new EventEmitter()
// 나중에 방출
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo')) {
// 이 내부 블록의 실행은 동기식이며 한 번에 하나의 이벤트를 처리합니다(await 사용 시에도). 동시 실행이 필요한 경우 사용하지 마십시오.
console.log(event) // ['bar'] [42] 출력
}
// 여기서는 도달할 수 없음
const { on, EventEmitter } = require('node:events')
;(async () => {
const ee = new EventEmitter()
// 나중에 방출
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo')) {
// 이 내부 블록의 실행은 동기식이며 한 번에 하나의 이벤트를 처리합니다(await 사용 시에도). 동시 실행이 필요한 경우 사용하지 마십시오.
console.log(event) // ['bar'] [42] 출력
}
// 여기서는 도달할 수 없음
})()
eventName
이벤트를 반복하는 AsyncIterator
를 반환합니다. EventEmitter
가 'error'
를 방출하면 예외를 throw합니다. 루프를 종료할 때 모든 리스너를 제거합니다. 각 반복에서 반환되는 value
는 방출된 이벤트 인수로 구성된 배열입니다.
<AbortSignal>을 사용하여 이벤트 대기 중을 취소할 수 있습니다.
import { on, EventEmitter } from 'node:events'
import process from 'node:process'
const ac = new AbortController()
;(async () => {
const ee = new EventEmitter()
// 나중에 방출
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// 이 내부 블록의 실행은 동기식이며 한 번에 하나의 이벤트를 처리합니다(await 사용 시에도). 동시 실행이 필요한 경우 사용하지 마십시오.
console.log(event) // ['bar'] [42] 출력
}
// 여기서는 도달할 수 없음
})()
process.nextTick(() => ac.abort())
const { on, EventEmitter } = require('node:events')
const ac = new AbortController()
;(async () => {
const ee = new EventEmitter()
// 나중에 방출
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// 이 내부 블록의 실행은 동기식이며 한 번에 하나의 이벤트를 처리합니다(await 사용 시에도). 동시 실행이 필요한 경우 사용하지 마십시오.
console.log(event) // ['bar'] [42] 출력
}
// 여기서는 도달할 수 없음
})()
process.nextTick(() => ac.abort())
events.setMaxListeners(n[, ...eventTargets])
추가됨: v15.4.0
n
<number> 0보다 크거나 같은 숫자.EventTarget
이벤트당 최대 리스너 수입니다....eventsTargets
<EventTarget[]> | <EventEmitter[]> 0개 이상의 <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
[Stable: 1 - Experimental]
Stable: 1 Stability: 1 - 실험적
signal
<AbortSignal>listener
<Function> | <EventListener>- 반환값: <Disposable>
abort
리스너를 제거하는 Disposable입니다.
제공된 signal
의 abort
이벤트를 한 번만 수신합니다.
abort
신호의 abort
이벤트를 수신하는 것은 안전하지 않으며, 신호를 가진 다른 제3자가 e.stopImmediatePropagation()
을 호출할 수 있으므로 리소스 누수로 이어질 수 있습니다. Node.js는 웹 표준을 위반하기 때문에 이를 변경할 수 없습니다. 또한 원래 API는 리스너를 제거하는 것을 쉽게 잊게 만듭니다.
이 API는 stopImmediatePropagation
이 리스너가 실행되는 것을 방지하지 않도록 이벤트를 수신하여 이러한 두 가지 문제를 해결함으로써 Node.js API에서 AbortSignal
을 안전하게 사용할 수 있도록 합니다.
더 쉽게 구독 취소할 수 있도록 disposable을 반환합니다.
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
추가됨: v17.4.0, v16.14.0
수동 비동기 추적이 필요한 EventEmitter
에 대해 EventEmitter
를 <AsyncResource>와 통합합니다. 특히, 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()
// 비동기 컨텍스트를 추적하지 않는 일반적인 EventEmitter의 'foo' 리스너는 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()
// 비동기 컨텍스트를 추적하지 않는 일반적인 EventEmitter의 'foo' 리스너는 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> Promise 거부 자동 캡처를 활성화합니다. 기본값:false
.name
<string> 비동기 이벤트의 유형입니다. 기본값:new.target.name
.triggerAsyncId
<number> 이 비동기 이벤트를 생성한 실행 컨텍스트의 ID입니다. 기본값:executionAsyncId()
.requireManualDestroy
<boolean>true
로 설정하면 객체가 가비지 콜렉션될 때emitDestroy
를 비활성화합니다. 리소스의asyncId
가 검색되고 중요 API의emitDestroy
가 해당 ID를 사용하여 호출되지 않는 한 일반적으로 (emitDestroy
가 수동으로 호출되더라도) 설정할 필요가 없습니다.false
로 설정하면 가비지 콜렉션 시emitDestroy
호출은 활성destroy
훅이 하나 이상 있는 경우에만 발생합니다. 기본값:false
.
eventemitterasyncresource.asyncId
- 유형: <number> 리소스에 할당된 고유한
asyncId
.
eventemitterasyncresource.asyncResource
- 유형: 기본 <AsyncResource>.
반환된 AsyncResource
객체에는 이 EventEmitterAsyncResource
에 대한 참조를 제공하는 추가 eventEmitter
속성이 있습니다.
eventemitterasyncresource.emitDestroy()
모든 destroy
훅을 호출합니다. 이 메서드는 한 번만 호출되어야 합니다. 두 번 이상 호출하면 오류가 발생합니다. 이 메서드는 반드시 수동으로 호출해야 합니다. 리소스가 GC에 의해 수집되도록 남겨두면 destroy
훅이 절대 호출되지 않습니다.
eventemitterasyncresource.triggerAsyncId
- 유형: <number>
AsyncResource
생성자에 전달되는 것과 동일한triggerAsyncId
.
EventTarget
및 Event
API
[히스토리]
버전 | 변경 사항 |
---|---|
v16.0.0 | EventTarget 오류 처리 변경 |
v15.4.0 | 더 이상 실험적이지 않음 |
v15.0.0 | EventTarget 및 Event 클래스가 이제 전역적으로 사용 가능 |
v14.5.0 | 추가됨: v14.5.0 |
EventTarget
및 Event
객체는 일부 Node.js 코어 API에서 노출하는 EventTarget
웹 API의 Node.js 특정 구현입니다.
const target = new EventTarget()
target.addEventListener('foo', event => {
console.log('foo 이벤트 발생!')
})
Node.js EventTarget
대 DOM EventTarget
Node.js EventTarget
와 EventTarget
웹 API 사이에는 두 가지 주요 차이점이 있습니다.
NodeEventTarget
대 EventEmitter
NodeEventTarget
객체는 특정 상황에서 EventEmitter
를 밀접하게 모방할 수 있도록 EventEmitter
API의 수정된 하위 집합을 구현합니다. NodeEventTarget
은 EventEmitter
의 인스턴스가 아니며 대부분의 경우 EventEmitter
대신 사용할 수 없습니다.
이벤트 리스너
이벤트 type
에 대해 등록된 이벤트 리스너는 JavaScript 함수이거나 값이 함수인 handleEvent
속성을 가진 객체일 수 있습니다.
두 경우 모두 핸들러 함수는 eventTarget.dispatchEvent()
함수에 전달된 event
인수로 호출됩니다.
비동기 함수를 이벤트 리스너로 사용할 수 있습니다. 비동기 핸들러 함수가 거부되면 거부는 캡처되어 EventTarget
오류 처리에 설명된 대로 처리됩니다.
하나의 핸들러 함수에서 발생하는 오류는 다른 핸들러가 호출되는 것을 방지하지 않습니다.
핸들러 함수의 반환 값은 무시됩니다.
핸들러는 항상 추가된 순서대로 호출됩니다.
핸들러 함수는 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
은 EventEmitter
와 같은 'error'
유형 이벤트에 대한 특별한 기본 처리를 구현하지 않습니다.
현재 오류는 process.on('uncaughtException')
에 도달하기 전에 먼저 process.on('error')
이벤트로 전달됩니다. 이 동작은 더 이상 사용되지 않으며 향후 릴리스에서 다른 Node.js API와 EventTarget
을 일치시키기 위해 변경될 예정입니다. process.on('error')
이벤트에 의존하는 코드는 새로운 동작과 일치하도록 조정되어야 합니다.
클래스: Event
[히스토리]
버전 | 변경 사항 |
---|---|
v15.0.0 | Event 클래스가 이제 전역 객체를 통해 사용 가능합니다. |
v14.5.0 | 추가됨: v14.5.0 |
Event
객체는 Event
웹 API를 적용한 것입니다. 인스턴스는 Node.js에 의해 내부적으로 생성됩니다.
event.bubbles
추가됨: v14.5.0
- 유형: <boolean> 항상
false
를 반환합니다.
Node.js에서는 사용되지 않으며 완성도를 위해 제공됩니다.
event.cancelBubble
추가됨: v14.5.0
[안정성: 3 - 레거시]
안정성: 3 안정성: 3 - 레거시: event.stopPropagation()
을 대신 사용하십시오.
- 유형: <boolean>
true
로 설정되면 event.stopPropagation()
의 별칭입니다. Node.js에서는 사용되지 않으며 완성도를 위해 제공됩니다.
event.cancelable
추가됨: v14.5.0
- 유형: <boolean> 이벤트가
cancelable
옵션으로 생성된 경우true
입니다.
event.composed
추가됨: v14.5.0
- 타입: <boolean> 항상
false
를 반환합니다.
Node.js에서는 사용되지 않으며 완성도를 위해 제공됩니다.
event.composedPath()
추가됨: v14.5.0
현재 EventTarget
을 유일한 항목으로 포함하는 배열을 반환하거나, 이벤트가 디스패치되지 않는 경우 빈 배열을 반환합니다. Node.js에서는 사용되지 않으며 완성도를 위해 제공됩니다.
event.currentTarget
추가됨: v14.5.0
- 타입: <EventTarget> 이벤트를 디스패치하는
EventTarget
.
event.target
의 별칭입니다.
event.defaultPrevented
추가됨: v14.5.0
- 타입: <boolean>
cancelable
이 true
이고 event.preventDefault()
가 호출된 경우 true
입니다.
event.eventPhase
추가됨: v14.5.0
- 타입: <number> 이벤트가 디스패치되지 않는 동안
0
을, 디스패치되는 동안2
를 반환합니다.
Node.js에서는 사용되지 않으며 완성도를 위해 제공됩니다.
event.initEvent(type[, bubbles[, cancelable]])
추가됨: v19.5.0
이벤트 생성자와 중복되며 composed
를 설정할 수 없습니다. Node.js에서는 사용되지 않으며 완성도를 위해 제공됩니다.
event.isTrusted
추가됨: v14.5.0
- 타입: <boolean>
<AbortSignal> "abort"
이벤트는 isTrusted
가 true
로 설정되어 방출됩니다. 다른 모든 경우에는 값이 false
입니다.
event.preventDefault()
추가됨: v14.5.0
cancelable
이 true
이면 defaultPrevented
속성을 true
로 설정합니다.
event.returnValue
추가됨: v14.5.0
[안정성: 3 - 레거시]
안정성: 3 안정성: 3 - 레거시: event.defaultPrevented
를 대신 사용하십시오.
- 타입: <boolean> 이벤트가 취소되지 않은 경우
true
.
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
<문자열>listener
<함수> | <EventListener>options
<객체>once
<불리언>true
이면, 리스너는 처음 호출될 때 자동으로 제거됩니다. 기본값:false
.passive
<불리언>true
이면, 리스너가Event
객체의preventDefault()
메서드를 호출하지 않을 것이라는 힌트로 사용됩니다. 기본값:false
.capture
<불리언> Node.js에서 직접 사용되지 않습니다. API 완성도를 위해 추가되었습니다. 기본값:false
.signal
<AbortSignal> 주어진 AbortSignal 객체의abort()
메서드가 호출되면 리스너가 제거됩니다.
type
이벤트에 대한 새로운 핸들러를 추가합니다. 주어진 listener
는 type
당, capture
옵션 값당 한 번만 추가됩니다.
once
옵션이 true
이면, type
이벤트가 다음에 디스패치된 후 listener
가 제거됩니다.
capture
옵션은 EventTarget
사양에 따라 등록된 이벤트 리스너를 추적하는 것 외에는 Node.js에서 기능적으로 사용되지 않습니다. 구체적으로, capture
옵션은 listener
를 등록할 때 키의 일부로 사용됩니다. 개별 listener
는 capture = false
로 한 번, capture = true
로 한 번 추가될 수 있습니다.
function handler(event) {}
const target = new EventTarget()
target.addEventListener('foo', handler, { capture: true }) // 첫 번째
target.addEventListener('foo', handler, { capture: false }) // 두 번째
// handler의 두 번째 인스턴스를 제거합니다.
target.removeEventListener('foo', handler)
// handler의 첫 번째 인스턴스를 제거합니다.
target.removeEventListener('foo', handler, { capture: true })
eventTarget.dispatchEvent(event)
추가됨: v14.5.0
event
<Event>- 반환값: <boolean> 이벤트의
cancelable
속성 값이 false이거나preventDefault()
메서드가 호출되지 않은 경우true
, 그렇지 않으면false
.
event.type
에 대한 핸들러 목록에 이벤트를 전파합니다.
등록된 이벤트 리스너는 등록된 순서대로 동기적으로 호출됩니다.
eventTarget.removeEventListener(type, listener[, options])
추가됨: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
이벤트 type
에 대한 핸들러 목록에서 listener
를 제거합니다.
클래스: CustomEvent
[히스토리]
버전 | 변경 사항 |
---|---|
v23.0.0 | 더 이상 실험적이지 않음. |
v22.1.0, v20.13.0 | CustomEvent가 안정화되었습니다. |
v19.0.0 | 더 이상 --experimental-global-customevent CLI 플래그 뒤에 있지 않음. |
v18.7.0, v16.17.0 | 추가됨: v18.7.0, v16.17.0 |
- 상속: <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 |
- 타입: <any> 초기화할 때 전달된 사용자 정의 데이터를 반환합니다.
읽기 전용.
클래스: NodeEventTarget
추가됨: v14.5.0
- 상속: <EventTarget>
NodeEventTarget
는 EventEmitter
API의 일부를 에뮬레이트하는 Node.js 전용 EventTarget
확장입니다.
nodeEventTarget.addListener(type, listener)
추가됨: v14.5.0
type
<string>listener
<Function> | <EventListener>- 반환값: <EventTarget> this
EventEmitter
API에 해당하는 EventTarget
클래스에 대한 Node.js 전용 확장입니다. addListener()
와 addEventListener()
의 유일한 차이점은 addListener()
가 EventTarget
에 대한 참조를 반환한다는 것입니다.
nodeEventTarget.emit(type, arg)
추가됨: v15.2.0
type
에 대한 처리기 목록에 arg
를 전달하는 EventTarget
클래스에 대한 Node.js 전용 확장입니다.
nodeEventTarget.eventNames()
추가됨: v14.5.0
- 반환값: <string[]>
이벤트 리스너가 등록된 이벤트 type
이름의 배열을 반환하는 EventTarget
클래스에 대한 Node.js 전용 확장입니다.
nodeEventTarget.listenerCount(type)
추가됨: v14.5.0
type
에 등록된 이벤트 리스너의 수를 반환하는 EventTarget
클래스에 대한 Node.js 전용 확장입니다.
nodeEventTarget.setMaxListeners(n)
추가됨: v14.5.0
n
<number>
EventTarget
클래스에 대한 Node.js 전용 확장으로, 최대 이벤트 리스너 수를 n
으로 설정합니다.
nodeEventTarget.getMaxListeners()
추가됨: v14.5.0
- 반환값: <number>
EventTarget
클래스에 대한 Node.js 전용 확장으로, 최대 이벤트 리스너 수를 반환합니다.
nodeEventTarget.off(type, listener[, options])
추가됨: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
반환값: <EventTarget> this
eventTarget.removeEventListener()
에 대한 Node.js 전용 별칭입니다.
nodeEventTarget.on(type, listener)
추가됨: v14.5.0
type
<string>listener
<Function> | <EventListener>- 반환값: <EventTarget> this
eventTarget.addEventListener()
에 대한 Node.js 전용 별칭입니다.
nodeEventTarget.once(type, listener)
추가됨: v14.5.0
type
<string>listener
<Function> | <EventListener>- 반환값: <EventTarget> this
주어진 이벤트 type
에 대한 once
리스너를 추가하는 EventTarget
클래스에 대한 Node.js 전용 확장입니다. once
옵션을 true
로 설정하여 on
을 호출하는 것과 같습니다.
nodeEventTarget.removeAllListeners([type])
추가됨: v14.5.0
type
<string>- 반환값: <EventTarget> this
EventTarget
클래스에 대한 Node.js 전용 확장입니다. type
이 지정되면 type
에 대해 등록된 모든 리스너를 제거하고, 그렇지 않으면 등록된 모든 리스너를 제거합니다.
nodeEventTarget.removeListener(type, listener[, options])
추가됨: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
반환값: <EventTarget> this
주어진 type
에 대한 listener
를 제거하는 EventTarget
클래스에 대한 Node.js 전용 확장입니다. removeListener()
와 removeEventListener()
의 유일한 차이점은 removeListener()
가 EventTarget
에 대한 참조를 반환한다는 것입니다.