1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 |
- 'use strict'
- const EventEmitter = require('events').EventEmitter
- /**
- * A CorkedEmitter is a variant of an EventEmitter where events emitted
- * wait for the appearance of the first listener of any kind. That is,
- * a CorkedEmitter will store all .emit()s it receives, to be replayed
- * later when an .on() is applied.
- * It is meant for situations where the consumers of the emitter are
- * unable to register listeners right away, and cannot afford to miss
- * any events emitted from the start.
- * Note that, whenever the first emitter (for any event) appears,
- * the emitter becomes uncorked and works as usual for ALL events, and
- * will not cache anything anymore. This is necessary to avoid
- * re-ordering emits - either everything is being buffered, or nothing.
- */
- function CorkedEmitter () {
- const self = this
- EventEmitter.call(self)
- /**
- * An array of arguments objects (array-likes) to emit on open.
- */
- self._outstandingEmits = []
- /**
- * Whether the normal flow of emits is restored yet.
- */
- self._opened = false
- // When the first listener appears, we enqueue an opening.
- // It is not done immediately, so that other listeners can be
- // registered in the same critical section.
- self.once('newListener', function () {
- setImmediate(function releaseStoredEvents () {
- self._opened = true
- self._outstandingEmits.forEach(function (args) {
- self.emit.apply(self, args)
- })
- })
- })
- }
- CorkedEmitter.prototype = Object.create(EventEmitter.prototype)
- CorkedEmitter.prototype.emit = function emit (eventName) {
- if (this._opened || eventName === 'newListener') {
- EventEmitter.prototype.emit.apply(this, arguments)
- } else {
- this._outstandingEmits.push(arguments)
- }
- }
- module.exports = CorkedEmitter
|