Skip to content

이벤트

[안정적: 2 - 안정적]

안정적: 2 안정성: 2 - 안정적

소스 코드: lib/events.js

Node.js 코어 API의 상당 부분은 특정 종류의 객체("emitter"라고 함)가 이름이 지정된 이벤트를 방출하여 Function 객체("listener"라고 함)를 호출하는 관용적인 비동기 이벤트 기반 아키텍처를 기반으로 구축됩니다.

예를 들어 net.Server 객체는 피어가 연결될 때마다 이벤트를 방출하고, fs.ReadStream은 파일이 열릴 때 이벤트를 방출하며, 스트림은 읽을 수 있는 데이터가 있을 때마다 이벤트를 방출합니다.

이벤트를 방출하는 모든 객체는 EventEmitter 클래스의 인스턴스입니다. 이러한 객체는 객체가 방출하는 명명된 이벤트에 하나 이상의 함수를 연결할 수 있도록 하는 eventEmitter.on() 함수를 제공합니다. 일반적으로 이벤트 이름은 카멜케이스 문자열이지만 유효한 JavaScript 속성 키를 사용할 수 있습니다.

EventEmitter 객체가 이벤트를 방출하면 해당 특정 이벤트에 연결된 모든 함수가 동기적으로 호출됩니다. 호출된 리스너가 반환하는 모든 값은 무시되고 삭제됩니다.

다음 예는 단일 리스너가 있는 간단한 EventEmitter 인스턴스를 보여줍니다. eventEmitter.on() 메서드는 리스너를 등록하는 데 사용되고, eventEmitter.emit() 메서드는 이벤트를 트리거하는 데 사용됩니다.

js
import { EventEmitter } from 'node:events'

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter()
myEmitter.on('event', () => {
  console.log('an event occurred!')
})
myEmitter.emit('event')
js
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 인스턴스를 참조하도록 설정됩니다.

js
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')
js
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 인스턴스를 참조하지 않습니다.

js
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')
js
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() 메서드를 사용하여 비동기 작동 모드로 전환할 수 있습니다.

js
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')
js
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() 메서드를 사용하여 리스너를 등록하면 해당 리스너는 지정된 이벤트가 발생할 때마다 호출됩니다.

js
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
js
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() 메서드를 사용하면 특정 이벤트에 대해 최대 한 번만 호출되는 리스너를 등록할 수 있습니다. 이벤트가 발생하면 리스너가 등록 해제된 후 호출됩니다.

js
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
js
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 프로세스가 종료됩니다.

js
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('whoops!'))
// Node.js를 throw하고 충돌시킴
js
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' 이벤트에 대한 리스너를 항상 추가해야 합니다.

js
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
js
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' 이벤트를 모니터링할 수 있습니다.

js
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하고 충돌시킴
js
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 함수를 사용하는 것은 문제가 될 수 있습니다. 예외가 발생할 경우 처리되지 않은 거부가 발생할 수 있기 때문입니다.

js
import { EventEmitter } from 'node:events'
const ee = new EventEmitter()
ee.on('something', async value => {
  throw new Error('kaboom')
})
js
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' 이벤트 핸들러로 라우팅합니다.

js
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
js
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 인스턴스의 기본값이 변경됩니다.

js
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)
js
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.0captureRejections 옵션 추가
v0.1.26추가됨: v0.1.26

EventEmitter 클래스는 node:events 모듈에 의해 정의되고 노출됩니다.

js
import { EventEmitter } from 'node:events'
js
const EventEmitter = require('node:events')

모든 EventEmitter는 새로운 리스너가 추가될 때 'newListener' 이벤트를, 기존 리스너가 제거될 때 'removeListener' 이벤트를 방출합니다.

다음 옵션을 지원합니다.

이벤트: 'newListener'

추가됨: v0.1.26

EventEmitter 인스턴스는 리스너가 내부 리스너 배열에 추가되기 전에 자체 'newListener' 이벤트를 방출합니다.

'newListener' 이벤트에 등록된 리스너에는 이벤트 이름과 추가될 리스너에 대한 참조가 전달됩니다.

이벤트가 리스너를 추가하기 전에 트리거된다는 사실은 미묘하지만 중요한 부작용이 있습니다. 'newListener' 콜백 내에서 동일한 name에 등록된 추가 리스너는 추가되고 있는 리스너 앞에 삽입됩니다.

js
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
js
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를 반환합니다.

js
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 세 번째 리스너에서
js
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

이미터가 리스너를 등록한 이벤트 목록을 포함하는 배열을 반환합니다. 배열의 값은 문자열 또는 Symbol입니다.

js
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) ]
js
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

EventEmitter에 대한 현재 최대 리스너 값을 반환합니다. 이 값은 emitter.setMaxListeners(n)으로 설정하거나 events.defaultMaxListeners의 기본값을 사용합니다.

emitter.listenerCount(eventName[, listener])

[히스토리]

버전변경 사항
v19.8.0, v18.16.0listener 인수 추가
v3.2.0추가됨: v3.2.0

eventName으로 명명된 이벤트를 수신 대기하는 리스너의 수를 반환합니다. listener가 제공되면 이벤트 리스너 목록에서 리스너가 발견된 횟수를 반환합니다.

emitter.listeners(eventName)

[히스토리]

버전변경 사항
v7.0.0.once()를 사용하여 연결된 리스너의 경우 이제 래퍼 함수 대신 원래 리스너를 반환합니다.
v0.1.26추가됨: v0.1.26

eventName으로 명명된 이벤트에 대한 리스너 배열의 복사본을 반환합니다.

js
server.on('connection', stream => {
  console.log('someone connected!')
})
console.log(util.inspect(server.listeners('connection')))
// 출력: [ [Function] ]

emitter.off(eventName, listener)

추가됨: v10.0.0

emitter.removeListener()의 별칭입니다.

emitter.on(eventName, listener)

추가됨: v0.1.101

eventName으로 명명된 이벤트에 대한 리스너 배열의 끝에 listener 함수를 추가합니다. listener가 이미 추가되었는지 확인하는 검사는 수행되지 않습니다. 동일한 eventNamelistener 조합을 여러 번 전달하는 여러 호출은 listener가 여러 번 추가되고 호출되는 결과를 초래합니다.

js
server.on('connection', stream => {
  console.log('someone connected!')
})

EventEmitter에 대한 참조를 반환하므로 호출을 연결할 수 있습니다.

기본적으로 이벤트 리스너는 추가된 순서대로 호출됩니다. 이벤트 리스너를 리스너 배열의 시작 부분에 추가하는 대안으로 emitter.prependListener() 메서드를 사용할 수 있습니다.

js
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
js
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으로 명명된 이벤트에 대한 일회성 listener 함수를 추가합니다. 다음 번에 eventName이 트리거되면 이 리스너가 제거된 후 호출됩니다.

js
server.once('connection', stream => {
  console.log('Ah, we have our first user!')
})

EventEmitter에 대한 참조를 반환하므로 호출을 연결할 수 있습니다.

기본적으로 이벤트 리스너는 추가된 순서대로 호출됩니다. emitter.prependOnceListener() 메서드는 이벤트 리스너를 리스너 배열의 처음에 추가하는 대안으로 사용할 수 있습니다.

js
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
js
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으로 명명된 이벤트의 리스너 배열의 처음에 listener 함수를 추가합니다. listener가 이미 추가되었는지 확인하는 검사는 수행되지 않습니다. eventNamelistener의 동일한 조합을 여러 번 전달하는 여러 호출은 listener가 여러 번 추가되고 호출되는 결과를 초래합니다.

js
server.prependListener('connection', stream => {
  console.log('someone connected!')
})

EventEmitter에 대한 참조를 반환하므로 호출을 연결할 수 있습니다.

emitter.prependOnceListener(eventName, listener)

추가됨: v6.0.0

eventName으로 명명된 이벤트에 대한 일회성 listener 함수를 listener 배열의 맨 앞에 추가합니다. 다음 번에 eventName이 트리거되면 이 listener는 제거된 후 호출됩니다.

js
server.prependOnceListener('connection', stream => {
  console.log('Ah, we have our first user!')
})

EventEmitter에 대한 참조를 반환하므로 호출을 체이닝할 수 있습니다.

emitter.removeAllListeners([eventName])

추가됨: v0.1.26

모든 listener 또는 지정된 eventName의 listener를 제거합니다.

다른 곳의 코드에 추가된 listener를 제거하는 것은 좋지 않은 방법이며, 특히 EventEmitter 인스턴스가 다른 구성 요소 또는 모듈(예: 소켓 또는 파일 스트림)에 의해 생성된 경우 더욱 그렇습니다.

EventEmitter에 대한 참조를 반환하므로 호출을 체이닝할 수 있습니다.

emitter.removeListener(eventName, listener)

추가됨: v0.1.26

eventName으로 명명된 이벤트의 listener 배열에서 지정된 listener를 제거합니다.

js
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를 제거하지 않는다는 것을 의미합니다. 후속 이벤트는 예상대로 동작합니다.

js
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
js
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가 제거됩니다.

js
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')
js
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

기본적으로 EventEmitter는 특정 이벤트에 10개 이상의 리스너가 추가되면 경고를 출력합니다. 이는 메모리 누수를 찾는 데 도움이 되는 유용한 기본값입니다. emitter.setMaxListeners() 메서드를 사용하면 이 특정 EventEmitter 인스턴스에 대한 제한을 수정할 수 있습니다. 무제한의 리스너 수를 나타내려면 값을 Infinity(또는 0)로 설정할 수 있습니다.

EventEmitter에 대한 참조를 반환하므로 호출을 체이닝할 수 있습니다.

emitter.rawListeners(eventName)

추가됨: v9.4.0

eventName으로 지정된 이벤트에 대한 리스너 배열의 복사본을 반환합니다. .once()에 의해 생성된 것과 같은 모든 래퍼를 포함합니다.

js
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')
js
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을 사용할 수 있습니다.

js
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) {
    // 여기서 리소스를 해제합니다.
  }
}
js
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() 메서드를 사용하여 이 경고를 일시적으로 방지할 수 있습니다.

defaultMaxListenersAbortSignal 인스턴스에는 영향을 미치지 않습니다. 개별 AbortSignal 인스턴스에 대한 경고 제한을 설정하기 위해 emitter.setMaxListeners(n)을 사용하는 것은 여전히 가능하지만, 기본적으로 AbortSignal 인스턴스는 경고하지 않습니다.

js
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))
})
js
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, typecount 속성을 갖습니다. 해당 name 속성은 'MaxListenersExceededWarning'으로 설정됩니다.

events.errorMonitor

추가됨: v13.6.0, v12.17.0

이 심볼은 'error' 이벤트만 모니터링하기 위한 리스너를 설치하는 데 사용됩니다. 이 심볼을 사용하여 설치된 리스너는 일반적인 'error' 리스너가 호출되기 전에 호출됩니다.

이 심볼을 사용하여 리스너를 설치해도 'error' 이벤트가 발생한 후 동작이 변경되지 않습니다. 따라서 일반적인 'error' 리스너가 설치되지 않은 경우 프로세스는 여전히 충돌합니다.

events.getEventListeners(emitterOrTarget, eventName)

추가됨: v15.2.0, v14.17.0

eventName으로 지정된 이벤트에 대한 리스너 배열의 복사본을 반환합니다.

EventEmitter의 경우 이것은 이미터에서 .listeners를 호출하는 것과 정확히 동일하게 동작합니다.

EventTarget의 경우 이벤트 대상에 대한 이벤트 리스너를 가져오는 유일한 방법입니다. 이는 디버깅 및 진단 목적으로 유용합니다.

js
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] ]
}
js
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

현재 설정된 최대 리스너 수를 반환합니다.

EventEmitter의 경우 이 메서드는 이터미터에서 .getMaxListeners를 호출하는 것과 동일하게 동작합니다.

EventTarget의 경우 이벤트 타겟의 최대 이벤트 리스너를 가져오는 유일한 방법입니다. 단일 EventTarget의 이벤트 핸들러 수가 설정된 최대값을 초과하면 EventTarget은 경고를 출력합니다.

js
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
}
js
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.0signal 옵션이 지원됩니다.
v11.13.0, v10.16.0추가됨: v11.13.0, v10.16.0

EventEmitter가 지정된 이벤트를 방출할 때 또는 대기 중에 EventEmitter'error'를 방출할 때 거부되는 Promise를 생성합니다. Promise는 지정된 이벤트에 방출된 모든 인수의 배열로 확인됩니다.

이 메서드는 의도적으로 일반적이며, 특별한 'error' 이벤트 의미 체계가 없고 'error' 이벤트를 수신하지 않는 웹 플랫폼 EventTarget 인터페이스와 함께 작동합니다.

js
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)
}
js
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' 이벤트 자체를 기다리는 데 사용되는 경우 특수 처리 없이 다른 종류의 이벤트와 동일하게 처리됩니다.

js
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
js
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>을 사용하여 이벤트 대기를 취소할 수 있습니다.

js
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!
js
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()가 이벤트를 놓칠 수 있습니다.

js
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'))
js
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()를 사용할 수 있습니다.

js
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'))
js
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에 등록된 주어진 eventName에 대한 수신기 수를 반환하는 클래스 메서드입니다.

js
import { EventEmitter, listenerCount } from 'node:events'

const myEmitter = new EventEmitter()
myEmitter.on('event', () => {})
myEmitter.on('event', () => {})
console.log(listenerCount(myEmitter, 'event'))
// 출력: 2
js
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일관성을 위해 highWaterMarklowWaterMark 옵션 지원. 이전 옵션도 여전히 지원됩니다.
v20.0.0close, 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() 메서드를 구현하는 이벤트 방출기에서만 지원됩니다.
  • 반환값: emitter에서 방출된 eventName 이벤트를 반복하는 <AsyncIterator>

js
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] 출력
}
// 여기서는 도달할 수 없음
js
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>을 사용하여 이벤트 대기 중을 취소할 수 있습니다.

js
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())
js
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

js
import { setMaxListeners, EventEmitter } from 'node:events'

const target = new EventTarget()
const emitter = new EventEmitter()

setMaxListeners(5, target, emitter)
js
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 - 실험적

제공된 signalabort 이벤트를 한 번만 수신합니다.

abort 신호의 abort 이벤트를 수신하는 것은 안전하지 않으며, 신호를 가진 다른 제3자가 e.stopImmediatePropagation()을 호출할 수 있으므로 리소스 누수로 이어질 수 있습니다. Node.js는 웹 표준을 위반하기 때문에 이를 변경할 수 없습니다. 또한 원래 API는 리스너를 제거하는 것을 쉽게 잊게 만듭니다.

이 API는 stopImmediatePropagation이 리스너가 실행되는 것을 방지하지 않도록 이벤트를 수신하여 이러한 두 가지 문제를 해결함으로써 Node.js API에서 AbortSignal을 안전하게 사용할 수 있도록 합니다.

더 쉽게 구독 취소할 수 있도록 disposable을 반환합니다.

js
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]()
  }
}
js
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 인스턴스에서 방출되는 모든 이벤트는 해당 비동기 컨텍스트 내에서 실행됩니다.

js
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')
})
js
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 클래스는 EventEmitterAsyncResource 자체와 동일한 메서드를 가지며 동일한 옵션을 사용합니다.

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 객체에는 이 EventEmitterAsyncResource에 대한 참조를 제공하는 추가 eventEmitter 속성이 있습니다.

eventemitterasyncresource.emitDestroy()

모든 destroy 훅을 호출합니다. 이 메서드는 한 번만 호출되어야 합니다. 두 번 이상 호출하면 오류가 발생합니다. 이 메서드는 반드시 수동으로 호출해야 합니다. 리소스가 GC에 의해 수집되도록 남겨두면 destroy 훅이 절대 호출되지 않습니다.

eventemitterasyncresource.triggerAsyncId

  • 유형: <number> AsyncResource 생성자에 전달되는 것과 동일한 triggerAsyncId.

EventTargetEvent API

[히스토리]

버전변경 사항
v16.0.0EventTarget 오류 처리 변경
v15.4.0더 이상 실험적이지 않음
v15.0.0EventTargetEvent 클래스가 이제 전역적으로 사용 가능
v14.5.0추가됨: v14.5.0

EventTargetEvent 객체는 일부 Node.js 코어 API에서 노출하는 EventTarget 웹 API의 Node.js 특정 구현입니다.

js
const target = new EventTarget()

target.addEventListener('foo', event => {
  console.log('foo 이벤트 발생!')
})

Node.js EventTarget 대 DOM EventTarget

Node.js EventTargetEventTarget 웹 API 사이에는 두 가지 주요 차이점이 있습니다.

NodeEventTargetEventEmitter

NodeEventTarget 객체는 특정 상황에서 EventEmitter를 밀접하게 모방할 수 있도록 EventEmitter API의 수정된 하위 집합을 구현합니다. NodeEventTargetEventEmitter의 인스턴스가 아니며 대부분의 경우 EventEmitter 대신 사용할 수 없습니다.

이벤트 리스너

이벤트 type에 대해 등록된 이벤트 리스너는 JavaScript 함수이거나 값이 함수인 handleEvent 속성을 가진 객체일 수 있습니다.

두 경우 모두 핸들러 함수는 eventTarget.dispatchEvent() 함수에 전달된 event 인수로 호출됩니다.

비동기 함수를 이벤트 리스너로 사용할 수 있습니다. 비동기 핸들러 함수가 거부되면 거부는 캡처되어 EventTarget 오류 처리에 설명된 대로 처리됩니다.

하나의 핸들러 함수에서 발생하는 오류는 다른 핸들러가 호출되는 것을 방지하지 않습니다.

핸들러 함수의 반환 값은 무시됩니다.

핸들러는 항상 추가된 순서대로 호출됩니다.

핸들러 함수는 event 객체를 변경할 수 있습니다.

js
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 프로세스를 종료합니다.

이벤트 리스너 내에서 예외를 발생시켜도 다른 등록된 핸들러가 호출되는 것을 중지하지 않습니다.

EventTargetEventEmitter와 같은 'error' 유형 이벤트에 대한 특별한 기본 처리를 구현하지 않습니다.

현재 오류는 process.on('uncaughtException')에 도달하기 전에 먼저 process.on('error') 이벤트로 전달됩니다. 이 동작은 더 이상 사용되지 않으며 향후 릴리스에서 다른 Node.js API와 EventTarget을 일치시키기 위해 변경될 예정입니다. process.on('error') 이벤트에 의존하는 코드는 새로운 동작과 일치하도록 조정되어야 합니다.

클래스: Event

[히스토리]

버전변경 사항
v15.0.0Event 클래스가 이제 전역 객체를 통해 사용 가능합니다.
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()을 대신 사용하십시오.

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

cancelabletrue이고 event.preventDefault()가 호출된 경우 true입니다.

event.eventPhase

추가됨: v14.5.0

  • 타입: <number> 이벤트가 디스패치되지 않는 동안 0을, 디스패치되는 동안 2를 반환합니다.

Node.js에서는 사용되지 않으며 완성도를 위해 제공됩니다.

event.initEvent(type[, bubbles[, cancelable]])

추가됨: v19.5.0

[안정적: 3 - 레거시]

안정적: 3 안정성: 3 - 레거시: WHATWG 사양에서는 이를 더 이상 사용하지 않는 것으로 간주하며 사용자는 전혀 사용해서는 안 됩니다.

이벤트 생성자와 중복되며 composed를 설정할 수 없습니다. Node.js에서는 사용되지 않으며 완성도를 위해 제공됩니다.

event.isTrusted

추가됨: v14.5.0

<AbortSignal> "abort" 이벤트는 isTrustedtrue로 설정되어 방출됩니다. 다른 모든 경우에는 값이 false입니다.

event.preventDefault()

추가됨: v14.5.0

cancelabletrue이면 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를 대신 사용하십시오.

event.target의 별칭.

event.stopImmediatePropagation()

추가됨: v14.5.0

현재 이벤트 리스너가 완료된 후 이벤트 리스너의 호출을 중지합니다.

event.stopPropagation()

추가됨: v14.5.0

Node.js에서는 사용되지 않으며 완성도를 위해 제공됩니다.

event.target

추가됨: v14.5.0

event.timeStamp

추가됨: v14.5.0

Event 객체가 생성된 시점의 밀리초 타임스탬프.

event.type

추가됨: v14.5.0

이벤트 유형 식별자.

클래스: EventTarget

[히스토리]

버전변경 사항
v15.0.0EventTarget 클래스는 이제 전역 객체를 통해 사용할 수 있습니다.
v14.5.0추가됨: v14.5.0

eventTarget.addEventListener(type, listener[, options])

[히스토리]

버전변경 사항
v15.4.0signal 옵션 지원 추가
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 이벤트에 대한 새로운 핸들러를 추가합니다. 주어진 listenertype당, capture 옵션 값당 한 번만 추가됩니다.

once 옵션이 true이면, type 이벤트가 다음에 디스패치된 후 listener가 제거됩니다.

capture 옵션은 EventTarget 사양에 따라 등록된 이벤트 리스너를 추적하는 것 외에는 Node.js에서 기능적으로 사용되지 않습니다. 구체적으로, capture 옵션은 listener를 등록할 때 키의 일부로 사용됩니다. 개별 listenercapture = false로 한 번, capture = true로 한 번 추가될 수 있습니다.

js
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에 대한 핸들러 목록에서 listener를 제거합니다.

클래스: CustomEvent

[히스토리]

버전변경 사항
v23.0.0더 이상 실험적이지 않음.
v22.1.0, v20.13.0CustomEvent가 안정화되었습니다.
v19.0.0더 이상 --experimental-global-customevent CLI 플래그 뒤에 있지 않음.
v18.7.0, v16.17.0추가됨: v18.7.0, v16.17.0

[안정성: 2 - 안정적]

안정성: 2 안정성: 2 - 안정적

CustomEvent 객체는 CustomEvent Web API의 적응입니다. 인스턴스는 Node.js에서 내부적으로 생성됩니다.

event.detail

[히스토리]

버전변경 사항
v22.1.0, v20.13.0CustomEvent가 안정화되었습니다.
v18.7.0, v16.17.0추가됨: v18.7.0, v16.17.0

[안정성: 2 - 안정적]

안정성: 2 안정성: 2 - 안정적

  • 타입: <any> 초기화할 때 전달된 사용자 정의 데이터를 반환합니다.

읽기 전용.

클래스: NodeEventTarget

추가됨: v14.5.0

NodeEventTargetEventEmitter API의 일부를 에뮬레이트하는 Node.js 전용 EventTarget 확장입니다.

nodeEventTarget.addListener(type, listener)

추가됨: v14.5.0

EventEmitter API에 해당하는 EventTarget 클래스에 대한 Node.js 전용 확장입니다. addListener()addEventListener()의 유일한 차이점은 addListener()EventTarget에 대한 참조를 반환한다는 것입니다.

nodeEventTarget.emit(type, arg)

추가됨: v15.2.0

  • type <string>
  • arg <any>
  • 반환값: <boolean> type에 등록된 이벤트 리스너가 있으면 true, 그렇지 않으면 false를 반환합니다.

type에 대한 처리기 목록에 arg를 전달하는 EventTarget 클래스에 대한 Node.js 전용 확장입니다.

nodeEventTarget.eventNames()

추가됨: v14.5.0

이벤트 리스너가 등록된 이벤트 type 이름의 배열을 반환하는 EventTarget 클래스에 대한 Node.js 전용 확장입니다.

nodeEventTarget.listenerCount(type)

추가됨: v14.5.0

type에 등록된 이벤트 리스너의 수를 반환하는 EventTarget 클래스에 대한 Node.js 전용 확장입니다.

nodeEventTarget.setMaxListeners(n)

추가됨: v14.5.0

EventTarget 클래스에 대한 Node.js 전용 확장으로, 최대 이벤트 리스너 수를 n으로 설정합니다.

nodeEventTarget.getMaxListeners()

추가됨: v14.5.0

EventTarget 클래스에 대한 Node.js 전용 확장으로, 최대 이벤트 리스너 수를 반환합니다.

nodeEventTarget.off(type, listener[, options])

추가됨: v14.5.0

eventTarget.removeEventListener()에 대한 Node.js 전용 별칭입니다.

nodeEventTarget.on(type, listener)

추가됨: v14.5.0

eventTarget.addEventListener()에 대한 Node.js 전용 별칭입니다.

nodeEventTarget.once(type, listener)

추가됨: v14.5.0

주어진 이벤트 type에 대한 once 리스너를 추가하는 EventTarget 클래스에 대한 Node.js 전용 확장입니다. once 옵션을 true로 설정하여 on을 호출하는 것과 같습니다.

nodeEventTarget.removeAllListeners([type])

추가됨: v14.5.0

EventTarget 클래스에 대한 Node.js 전용 확장입니다. type이 지정되면 type에 대해 등록된 모든 리스너를 제거하고, 그렇지 않으면 등록된 모든 리스너를 제거합니다.

nodeEventTarget.removeListener(type, listener[, options])

추가됨: v14.5.0

주어진 type에 대한 listener를 제거하는 EventTarget 클래스에 대한 Node.js 전용 확장입니다. removeListener()removeEventListener()의 유일한 차이점은 removeListener()EventTarget에 대한 참조를 반환한다는 것입니다.