corked_emitter.js 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. 'use strict'
  2. const EventEmitter = require('events').EventEmitter
  3. /**
  4. * A CorkedEmitter is a variant of an EventEmitter where events emitted
  5. * wait for the appearance of the first listener of any kind. That is,
  6. * a CorkedEmitter will store all .emit()s it receives, to be replayed
  7. * later when an .on() is applied.
  8. * It is meant for situations where the consumers of the emitter are
  9. * unable to register listeners right away, and cannot afford to miss
  10. * any events emitted from the start.
  11. * Note that, whenever the first emitter (for any event) appears,
  12. * the emitter becomes uncorked and works as usual for ALL events, and
  13. * will not cache anything anymore. This is necessary to avoid
  14. * re-ordering emits - either everything is being buffered, or nothing.
  15. */
  16. function CorkedEmitter () {
  17. const self = this
  18. EventEmitter.call(self)
  19. /**
  20. * An array of arguments objects (array-likes) to emit on open.
  21. */
  22. self._outstandingEmits = []
  23. /**
  24. * Whether the normal flow of emits is restored yet.
  25. */
  26. self._opened = false
  27. // When the first listener appears, we enqueue an opening.
  28. // It is not done immediately, so that other listeners can be
  29. // registered in the same critical section.
  30. self.once('newListener', function () {
  31. setImmediate(function releaseStoredEvents () {
  32. self._opened = true
  33. self._outstandingEmits.forEach(function (args) {
  34. self.emit.apply(self, args)
  35. })
  36. })
  37. })
  38. }
  39. CorkedEmitter.prototype = Object.create(EventEmitter.prototype)
  40. CorkedEmitter.prototype.emit = function emit (eventName) {
  41. if (this._opened || eventName === 'newListener') {
  42. EventEmitter.prototype.emit.apply(this, arguments)
  43. } else {
  44. this._outstandingEmits.push(arguments)
  45. }
  46. }
  47. module.exports = CorkedEmitter