Refactor middleware surface
chandlerprall opened this issue · comments
Middleware code was introduced to support string selectors. It exists as a way to process arguments for some functions and I think is too targeted for those functions.
Existing middleware:
- string selectors
- Immutable.js state
I think the correct surfaces for middleware to target are:
- processing selectors (allows for non-array-of-strings selectors)
- state getters (processing of data, change underlying structure)
- state setters (processing of data, change underlying structure)
- event dispatching (intercept/modify events & payloads)
- state subscription (allow subscriber functions to be wrapped)
- calling of subscribers (allow subscribers to be exposed to more functionality, is probably a very useful hook for debug tools)
- testing for state equality, both in
setPartialState
and before calling a subscriber (this functionality isn't present yet, but (will be in 3.0)[https://github.com//issues/13])
Current middleware implementation will call all middleware for a function and use that output. I think this should change to Express-style where the middleware decides if it passes control to the next layer or returns the result.
@hartzis anything you've seen from the community that the above list is missing, or that another project is doing really well?
@michaelmerrill especially thinking about developer tools, anything missing from the above list?
I'll try to give this a more in depth reading when i'm more fully here, lol. but just a quick view i dont see async support explicitly called out, thinking like a redux-saga
implementation?
from redux docs:
- It does a bit of trickery to make sure that if you call store.dispatch(action) from your middleware instead of next(action), the action will actually travel the whole middleware chain again, including the current middleware. This is useful for asynchronous middleware, as we have seen previously.
http://redux.js.org/docs/advanced/Middleware.html#attempt-6-naïvely-applying-the-middleware
I see the point above, event dispatching (intercept/modify events & payloads)
, kind of like a catch all for this
Async is a defacto feature due to events being separated from state read/write. This both simplifies and complicates our middleware. Simplifies because each middleware stack only has to deal with one concept, complicates because we need multiple types of middleware.
At any point a middleware could Do Other Things, but those would be from the same exposed api calls which would naturally go through their own middleware chains, etc.