Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #37 from atom/fb-mdt-track-subscriptions
Track active subscriptions and clean up when emitter is disposed
  • Loading branch information
matthewwithanm committed May 17, 2018
2 parents 5ef3155 + 76700a6 commit 0301fca
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
16 changes: 16 additions & 0 deletions spec/emitter-spec.coffee
Expand Up @@ -96,6 +96,22 @@ describe "Emitter", ->
emitter.emit 'foo', 'bar'
expect(emittedValue).toBe 'bar'

describe "dispose", ->
it "disposes of all listeners", ->
emitter = new Emitter
disposable1 = emitter.on 'foo', ->
disposable2 = emitter.once 'foo', ->
emitter.dispose()
expect(disposable1.disposed).toBe true
expect(disposable2.disposed).toBe true

it "doesn't keep track of disposed disposables", ->
emitter = new Emitter
disposable = emitter.on 'foo', ->
expect(emitter.subscriptions.disposables.size).toBe 1
disposable.dispose()
expect(emitter.subscriptions.disposables.size).toBe 0

describe "when a handler throws an exception", ->
describe "when no exception handlers are registered on Emitter", ->
it "throws exceptions as normal, stopping subsequent handlers from firing", ->
Expand Down
14 changes: 13 additions & 1 deletion src/emitter.coffee
@@ -1,4 +1,5 @@
Disposable = require './disposable'
CompositeDisposable = require './composite-disposable'

# Essential: Utility class to be used when implementing event-based APIs that
# allows for handlers registered via `::on` to be invoked with calls to
Expand Down Expand Up @@ -64,10 +65,13 @@ class Emitter

# Public: Clear out any existing subscribers.
clear: ->
@subscriptions?.dispose()
@subscriptions = new CompositeDisposable
@handlersByEventName = {}

# Public: Unsubscribe all handlers.
dispose: ->
@subscriptions.dispose()
@handlersByEventName = null
@disposed = true

Expand Down Expand Up @@ -99,7 +103,15 @@ class Emitter
else
@handlersByEventName[eventName] = [handler]

new Disposable(@off.bind(this, eventName, handler))
# When the emitter is disposed, we want to dispose of all subscriptions.
# However, we also need to stop tracking disposables when they're disposed
# from outside, otherwise this class will hold references to all the
# disposables it created (instead of just the active ones).
cleanup = new Disposable =>
@subscriptions.remove cleanup
@off(eventName, handler)
@subscriptions.add cleanup
cleanup

# Public: Register the given handler function to be invoked the next time an
# events with the given name is emitted via {::emit}.
Expand Down

0 comments on commit 0301fca

Please sign in to comment.