Redux store the state of whole app into a single object. Which make the system’s state transition predictable and manageable. I try to apply Redux as an event system in backend. But unfortunately, it does not work.
How I use Redux in server side
My idea is, every time user send a request to server, we queue it up (add the request to store). After that the server will take action base on the state. The server subscribes the change of store and decide which action to take.
1 | (Server router get request) -> (dispatch action) -> (reducer put the request in the state) |
The diagram looks good, the logic flow is very clear. But there are lots of problems during implementation
Server action care actions, not states
In server side, the most logic only care ‘changes’, not ‘state’. Take web server as an example.
At first, there are no request, so the store looks like {queue: []}
.
When there is a ‘index.html’ request, I will store the request in the queue and start processing it. The store looks like {queue: ['index.html']}
.
If we get ‘index.html’ request from another user, we can found there is a same request. From the app state, we don’t know we are computing the result or not, we don’t know should we process the request.
Therefore, we have to store the state of request. like1
2
3
4
5{
queue: [
{page:'index.html', state:'processing'}
]
}
And we need to have lots of action and reducer to transit the state of request.
These kind of state does not means much in server side. If the request is processing, we only need to wait, we don’t have logic hooked on the processing
state. But in client side, we may have a lot UI to update when the request is processing, the state will be very useful to prevent user from confusion.
Short conclusion: Redux keeps all app state in a clear way. It is very important in client side, because we need to guarantee the data present to user is consistent and up-to-date. But in server side logic, we only care “what is do we need to process”, instead of “what are we processing now”. Using “state first” approach in server side introduce lots of boilerplate code.
Hook and Anchor pattern implementation is complex in Redux
Hook and anchor pattern is useful in server side, like the the_content
hook in Wordpress, which will be call before the post content sent to client, allow programmer inject customization content component easily. But in Redux, the implementation is not very straight forward.
1 | const reducer = (action, state) => { |
To implement the filter, we need to have 2 action to change the state to preparing and running. Because the ‘event subscriber’ in Redux can only see the state, we need to create a short ‘section’ to notify the subscriber. The implementation is more complex than the pub-sub.
Difficult to handle async hook handler in Redux
As dispatch does not return the anything about the subscriber, don’t know what subscriber did. If the subscriber is async, we cannot know it is finished or not. In some scenarios, it is a big problem.
For example, I want to insert the author data in post content, we need to run getAuthorAsync()
before sent the content. We cannot guarantee getAuthorAsync()
finished before fetchPost()
using dispatch()
.
In another implementation, we can implement this in a very simple way.1
2
3
4
5
6
7
8
9
10// Return all return value of hook handlers
const handlers = willFetchPostHooks();
Promise.all(handlers)
.then(() => {
return fetchPost();
})
.then((post) => {
...
return Promise.all(didFetchPostHooks());
})
Asynchronous hooks are very common in server side, as most task in backend take a longer process time. But in client side, it is not a big problem, as most of the action (UI update) are short and synchronous.
Better way in server side
Redux separate the state of each component, and store them in a single store. But we don’t need to do it in server side, because server side logic don’t have lots of share states. Using traditional OOP, each object take care of their own states may be good enough.