1. What is it?
Middleware (Middleware
) in computers is a type of software between application systems and system software. It uses the basic services (functions) provided by system software. Connecting various parts or different applications on the network application can achieve the purpose of resource sharing and function sharing
We knowredux
the entire workflow. Whenaction
is sent, reducer
immediately calculatesstate
, the whole process is a synchronous operation.
Then if you want to support asynchronous operations, or support error handling and log monitoring, you can use middleware.
In Redux, middleware is placed in the dispatch process and is intercepted during the dispatch action, as shown above.
It is essentially a function that has modified the store.dispatch method and added other functions between the two steps of issuing Action and executing Reducer.
2. Commonly used middleware
redux-thunk
: used for asynchronous operations
redux-logger
: used for logging
redux-promise
redux-saga
The above-mentioned middlewares need to be registered throughapplyMiddlewares
. The function is to form all the middlewares into an array, execute them in sequence, and then pass them into createStore as the second parameter< /span>
import {
createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import createLogger rom 'redux-logger'
const logger = createLogger()
const store = createStore(reducer, applyMiddleware(thunk, logger)) // 按顺序执行 从右到左
logger implementation
// 自己修改dispatch,增加logger
let next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action)
next(action)
console.log('next state', store.getState())
}
redux-thunk
After adding thunk middleware, asynchronous operations can be performed
redux-thunk is the asynchronous processing middleware recommended by the official website
By default dispatch(action), action needs to be a JavaScript object
redux-thunk middleware will determine the type of data you are currently passing in. If it is a function, it will pass in the parameter value (dispatch, getState) to the function.
Used by dispatch function After we dispatch the action again
, the getState function takes into account that some of our subsequent operations need to rely on the original state, so that we can obtain some previous states
So dispatch can be written in the form of the following function:
const getHomeMultidataAction = () => {
return (dispatch) => {
axios.get("http://xxx.xx.xx.xx/test").then(res => {
const data = res.data.data;
dispatch(changeBannersAction(data.banner.list));
dispatch(changeRecommendsAction(data.recommend.list));
})
}
}
dispatch(addTodo(text))
dispatch(addTodoAsync(text))
redux data flow diagram:
3. Implementation Principle
First look at the source code of applyMiddlewares
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer);
var dispatch = store.dispatch;
var chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
};
chain = middlewares.map(middleware => middleware(middlewareAPI));
dispatch = compose(...chain)(store.dispatch);
return {
...store, dispatch}
}
}
All middleware are put into an array chain, then nested for execution, and finally store.dispatch is executed. As you can see, the two methods getState and dispatch are available inside the middleware (middlewareAPI).
In the above study, we learned the basic use of redux-thunk
Internally, dispatch will be judged and then the corresponding operation will be performed. The principle is as follows:
function patchThunk(store) {
letnext = store.dispatch;
function dispatchAndThunk(action) {
if (typeof action === "function") {
action(store.dispatch, store.getState);
} else {
next(action);
}
}
store.dispatch = dispatchAndThunk;
}
The principle of implementing a log output is also very simple, as follows:
let next = store.dispatch;
function dispatchAndLog(action) {
console.log("dispatching:", addAction(10));
next(addAction(5));
console.log("新的state:", store.getState());
}
store.dispatch = dispatchAndLog;