Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unsubscribe call behaves unexpectedly #34

Closed
tsgautier opened this issue May 1, 2013 · 3 comments
Closed

unsubscribe call behaves unexpectedly #34

tsgautier opened this issue May 1, 2013 · 3 comments
Assignees

Comments

@tsgautier
Copy link

I'm trying to implement something like a one-time listener. However, unsubscribing at certain times behaves unexpectedly. Here's some code:

p = require 'postal'

postal = new p()

channel = postal.channel ''

subscription1 = channel.subscribe 'test', ->
  console.log '1 received message'

subscription2 = channel.subscribe 'test', ->
  console.log '2 received message'

channel.publish 'test'
subscription1.unsubscribe()
channel.publish 'test'

The above code behaves as expected, the output is as follows:

1 received message
2 received message
2 received message

However, to implement the "one-time" I did something like this:

p = require 'postal'

postal = new p()

channel = postal.channel ''

subscription1 = channel.subscribe 'test', ->
  console.log '1 received message'
  subscription1.unsubscribe()

subscription2 = channel.subscribe 'test', ->
  console.log '2 received message'

channel.publish 'test'
channel.publish 'test'

This outputs:

1 received message
2 received message

Which is pretty unexpected. Somehow the subscription1.unsubscribe() is unsubscribing both subscriptions.

@ifandelse
Copy link
Contributor

@tsgautier Sorry about the trouble! Looking at this right now....

@ghost ghost assigned ifandelse May 1, 2013
@tsgautier
Copy link
Author

no problem - surprisingly, nextTick works, but leaves the code susceptible to multiple deliveries, so a flag is required to protect that, here's an approximation:

p = require 'postal'

postal = new p()

channel = postal.channel ''

delivered = false
subscription1 = channel.subscribe 'test', ->
  return if delivered
  delivered = true
  console.log '1 received message'
  process.nextTick -> subscription1.unsubscribe()

subscription2 = channel.subscribe 'test', ->
  console.log '2 received message'

channel.publish 'test'
channel.publish 'test'

ifandelse added a commit that referenced this issue May 1, 2013
…ncorrectly handling a mutating array of subscribers as it iterated over them. I also fixed the once() call to return the instance.
@ifandelse
Copy link
Contributor

This issue should be resolved - sorry for the woes. I should know better than to iterate over mutating arrays. :-)
Unsubscribe calls are now queued to occur after the publish has completed, but any subscriber that unsubscribes during the publish is immediately marked inactive, so the callback won't be invoked again.

One other thing, you actually don't need the new when you invoke postal = new p(). Instead you can opt for:

postal = require('postal')()
# OR
p = require 'postal'
postal = p()

The node module just returns a factory function that optionally takes underscore as a dependency (it requires underscore for you if it's not passed). This approach is used so that postal and any add-ons are all accessing the same instances of modules...

Let me know if you run into any other issues.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants