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

Any way to control the priority of subscription callbacks? #404

Closed
ciathyza opened this issue Apr 4, 2019 · 5 comments

Comments

@ciathyza
Copy link

commented Apr 4, 2019

In ReSwift is there any way to control the priority of callbacks that store subscribers receive? In our project we want to use use several non-view StoreSubscriber-adhering classes that should for example have different priorities of when they are called back, e.g. a network class might need to be notified earlier than another store subscriber.

How can this be controlled in ReSwift?

@DivineDominion

This comment has been minimized.

Copy link
Contributor

commented Apr 4, 2019

In short, you can't. (Since subscribers are stored in an array, the order of subscription triggering is predictable. But that's brittle. And the point is that you shouldn't make your subscribers depend on this.)

From the times I wrestled with issues like this, I most of the time ended up with different actions affecting different states that trigger different subscribers. My suggestion: try to figure out if you should really split the state that all the subscribers subscribe to. It may sometimes be beneficial to seemingly duplicate substates with similar properties when the intent is different. Because then all the subscribers (e.g. network and view presenters) can evolve independently.

Take a NetworkRequest substate with empty, pending, failure and success cases. This is observed by a NetworkService which processes the results. For example, take the success event's result and dispatch an action to reset it to the empty state. With the success result, you can then do other things, like dispatch an action that stores the result permanently in another substate (e.g. a Tweets list) which in turn affects the subscribers of this substate.

If you want to directly control the order of effects, you may always use delegation. Have 1 subscriber that delegates the substate to interested parties in sequence. To have sequential coupling in a method will work and be intelligible, while ReSwift's internals are too opaque for this purpose.

+-----------+
|           |
|   State   |
|           |
+-----+-----+
      |
      |
      v
+-----+-----+
|           |
| Subscriber|
|           |
+-----+-----+
      |
      +----------------+
   1  |                |  2
+-----v-----+   +------v------+
|           |   |             |
| Network   |   |  Presenter  |
| something |   |             |
+-----------+   +-------------+
@danielmartinprieto

This comment has been minimized.

Copy link
Contributor

commented Apr 4, 2019

You can do this using the middleware.

The middleware chain is always called in the order you set at store configuration time. With it, you can take a dispatched action and hold it, apply side effects (you're talking about a Network class, so I guess you would want to do something like firing a new request after an action has been dispatched, or changing its auth token) and then let it pass through to your reducers. You can even stop that action from reaching the reducers, or dispatch new ones.

As a rule of thumb, I use subscribers to change my views and the middleware to apply other kind of side effects.

@mjarvis

This comment has been minimized.

Copy link
Member

commented Apr 4, 2019

+1 to both comments above, with a little note:

Since subscribers are stored in an array, the order of subscription triggering is predictable. But that's brittle. And the point is that you shouldn't make your subscribers depend on this.

This is untrue as of ReSwift 4.1, in which they are stored as a Set, which validates the comment of it being brittle. You should never depend on call order from a 3rd party (or system) framework, unless it is explicitly documented.

@DivineDominion

This comment has been minimized.

Copy link
Contributor

commented Apr 5, 2019

🤦‍♂️ See, that's what I meant :)

@DivineDominion

This comment has been minimized.

Copy link
Contributor

commented Jun 17, 2019

Closing this since there was no activity for a while.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.