GeezerVison is showing github.com — events: allow monitoring error events · nodejs/node@62d3beb
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/events.md +25Lines changed: 25 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -155,6 +155,18 @@ myEmitter.emit('error', new Error('whoops!')); | 155 | 155 | // Prints: whoops! there was an error | 156 | 156 | ``` | 157 | 157 |
| | 158 | +It is possible to monitor `'error'` events without consuming the emitted error | | 159 | +by installing a listener using the symbol `errorMonitor`. | | 160 | + | | 161 | +```js | | 162 | +const myEmitter = new MyEmitter(); | | 163 | +myEmitter.on(EventEmitter.errorMonitor, (err) => { | | 164 | + MyMonitoringTool.log(err); | | 165 | +}); | | 166 | +myEmitter.emit('error', new Error('whoops!')); | | 167 | +// Still throws and crashes Node.js | | 168 | +``` | | 169 | + | 158 | 170 | ## Capture Rejections of Promises | 159 | 171 |
| 160 | 172 | > Stability: 1 - captureRejections is experimental. | @@ -348,6 +360,19 @@ the event emitter instance, the event’s name and the number of attached | 348 | 360 | listeners, respectively. | 349 | 361 | Its `name` property is set to `'MaxListenersExceededWarning'`. | 350 | 362 |
| | 363 | +### `EventEmitter.errorMonitor` | | 364 | +<!-- YAML | | 365 | +added: REPLACEME | | 366 | +--> | | 367 | + | | 368 | +This symbol shall be used to install a listener for only monitoring `'error'` | | 369 | +events. Listeners installed using this symbol are called before the regular | | 370 | +`'error'` listeners are called. | | 371 | + | | 372 | +Installing a listener using this symbol does not change the behavior once an | | 373 | +`'error'` event is emitted, therefore the process will still crash if no | | 374 | +regular `'error'` listener is installed. | | 375 | + | 351 | 376 | ### `emitter.addListener(eventName, listener)` | 352 | 377 | <!-- YAML | 353 | 378 | added: v0.1.26 | |
Collapse file Copy file name to clipboardExpand all lines: lib/events.js +12-2Lines changed: 12 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -56,6 +56,7 @@ const { | 56 | 56 | } = require('internal/util/inspect'); | 57 | 57 |
| 58 | 58 | const kCapture = Symbol('kCapture'); | | 59 | +const kErrorMonitor = Symbol('events.errorMonitor'); | 59 | 60 |
| 60 | 61 | function EventEmitter(opts) { | 61 | 62 | EventEmitter.init.call(this, opts); | @@ -84,6 +85,13 @@ ObjectDefineProperty(EventEmitter, 'captureRejections', { | 84 | 85 | enumerable: true | 85 | 86 | }); | 86 | 87 |
| | 88 | +ObjectDefineProperty(EventEmitter, 'errorMonitor', { | | 89 | + value: kErrorMonitor, | | 90 | + writable: false, | | 91 | + configurable: true, | | 92 | + enumerable: true | | 93 | +}); | | 94 | + | 87 | 95 | // The default for captureRejections is false | 88 | 96 | ObjectDefineProperty(EventEmitter.prototype, kCapture, { | 89 | 97 | value: false, | @@ -257,9 +265,11 @@ EventEmitter.prototype.emit = function emit(type, ...args) { | 257 | 265 | let doError = (type === 'error'); | 258 | 266 |
| 259 | 267 | const events = this._events; | 260 | | - if (events !== undefined) | | 268 | + if (events !== undefined) { | | 269 | + if (doError && events[kErrorMonitor] !== undefined) | | 270 | + this.emit(kErrorMonitor, ...args); | 261 | 271 | doError = (doError && events.error === undefined); | 262 | | - else if (!doError) | | 272 | + } else if (!doError) | 263 | 273 | return false; | 264 | 274 |
| 265 | 275 | // If there is no 'error' event listener then throw. | |
Collapse file Copy file name to clipboard +32Lines changed: 32 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | +const common = require('../common'); | | 3 | +const assert = require('assert'); | | 4 | +const EventEmitter = require('events'); | | 5 | + | | 6 | +const EE = new EventEmitter(); | | 7 | +const theErr = new Error('MyError'); | | 8 | + | | 9 | +EE.on( | | 10 | + EventEmitter.errorMonitor, | | 11 | + common.mustCall(function onErrorMonitor(e) { | | 12 | + assert.strictEqual(e, theErr); | | 13 | + }, 3) | | 14 | +); | | 15 | + | | 16 | +// Verify with no error listener | | 17 | +common.expectsError( | | 18 | + () => EE.emit('error', theErr), theErr | | 19 | +); | | 20 | + | | 21 | +// Verify with error listener | | 22 | +EE.once('error', common.mustCall((e) => assert.strictEqual(e, theErr))); | | 23 | +EE.emit('error', theErr); | | 24 | + | | 25 | + | | 26 | +// Verify it works with once | | 27 | +process.nextTick(() => EE.emit('error', theErr)); | | 28 | +assert.rejects(EventEmitter.once(EE, 'notTriggered'), theErr); | | 29 | + | | 30 | +// Only error events trigger error monitor | | 31 | +EE.on('aEvent', common.mustCall()); | | 32 | +EE.emit('aEvent'); |
|