-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
Prevent invalidating subscription iterator #1438
Conversation
…ously calling unsubscribe
src/store.js
Outdated
@@ -100,7 +100,7 @@ export class Store { | |||
handler(payload) | |||
}) | |||
}) | |||
this._subscribers.forEach(sub => sub(mutation, this.state)) | |||
this._subscribers.slice().forEach(sub => sub(mutation, this.state)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm open to cleaner/faster ways to generate a shallow copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it's ok to use slice
for that.
What is the actual use case that unsubscribing in another subscribe handler by the way? |
It can be useful in scenarios where you want to teardown a subscription when a particular mutation occurs (e.g. logout), or mutations that are guaranteed to only be committed N times during the lifetime of the app (e.g. 1 login from OAuth flow, as another login would have to reload the page). |
src/store.js
Outdated
@@ -100,7 +100,7 @@ export class Store { | |||
handler(payload) | |||
}) | |||
}) | |||
this._subscribers.forEach(sub => sub(mutation, this.state)) | |||
this._subscribers.slice().forEach(sub => sub(mutation, this.state)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it's ok to use slice
for that.
@@ -100,7 +100,7 @@ export class Store { | |||
handler(payload) | |||
}) | |||
}) | |||
this._subscribers.forEach(sub => sub(mutation, this.state)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you write some comment to share the context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
@@ -100,7 +100,7 @@ export class Store { | |||
handler(payload) | |||
}) | |||
}) | |||
this._subscribers.forEach(sub => sub(mutation, this.state)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we also need to do the same thing for _actionSubscribers
in dispatch
method.
https://github.com/vuejs/vuex/blob/dev/src/store.js#L132
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, I've shared it through a new notifySubscribers
function.
…ynchronously calling unsubscribe
Hi @ktsn, are there any other changes you'd like to see in this PR? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
Hey @cngu, thank you for your time and effort spent on this PR, contributions like yours help make Vue better for everyone. Cheers! 💚 |
* Prevent users from invalidating the subscription iterator by synchronously calling unsubscribe * Prevent users from invalidating the action subscription iterator by synchronously calling unsubscribe * Fix commit subscribers argument invocation
This change shallow copies
_subscribers
before iterating over it, in-case one of the subscription listeners attempts to unsubscribe synchronously and invalidate the iterator.