哈喽,大家好呀,我是前端理想哥,今天我们来聊聊Redux的中间件机制。即 Middleware
如果大家用过一些服务端的框架,像 Express 或 Koa,应该对 Middleware 并不陌生,在这些框架中,middlewares可以让你在发起请求和接收响应中间添加一些功能,比如添加 CORS 标头、记录日志、压缩等。
Redux的中间件机制和这些服务端框架的在概念上是相似的,大家可以看下这张图来深入了解下。
如果没有中间件机制,当我们触发了action后,就会直接去执行reducer修改状态值,然后更新UI了,中间件机制的出现,就像一个中间商一样,在action和reducer中间又隔了一层甚至多层,可以让你加强和拓展dispatch的功能,比如日志记录、故障监控上报、与异步 API 通信等等。
在图中,大家可以看到中间件之间其实有这么几个特点,第一 ,每个中间件都是实现了一个功能,第二,中间件之间可以实现链式调用,即每个中间件都可以访问上一个中间件,第三,为了规范化,所有的中间件都是统一封装并注册。
所以,接下来,我们从上面三个特点出发,一起来实现一个中间件。
首先,我们先来实现这样一个功能:记录应用程序中每个 action 的调用,连同调用 action 后计算的状态,你可能第一时间会想到:那我重写下dispatch方法不就行了,就像图中这样:
import {createStore} from 'redux'
import reducer from './reducers'
let store = createStore(reducer)
// 缓存原生的siapatch
const next = store.dispatch
// 重写dispatch方法
store.dispatch = function(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state',
store.getState())
return result
}
export default store
图中代码主要是先把原生的dispatch方法缓存起来,然后重写dispatch方法,最后调用缓存起来的dispatch方法, 但是,这种方式是不推荐的,写法太简单了而且没办法后续链式调用,那我们再按照图中方案继续改造下,
function logger(store) {
// next 代表下一个中间件
return function
wrapDispatchToAddLogging(next) {
// action动作
return function
dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
}
}
大家可以看到图中的代码。我们通过 return 新的 dispatch 函数,和 next() 方法,实现了中间件之间的链式调用
接下来,我们再来实现一个函数,将所有的中间件都统一封装并注册,就像图中这样:
function applyMiddleware(store, middlewares) {
middlewares = middlewares.slice()
middlewares.reverse()
let dispatch = store.dispatch
middlewares.forEach(middleware =>
(dispatch = middleware(store)(dispatch)))
return Object.assign({}, store, { dispatch })
}
图中代码中实现的功能,就是在遍历所有的中间件并拓展到dispatch功能中,最终,可以按照图中这样使用即可
import {
createStore,
combineReducers,
applyMiddleware } from 'redux'
const todoApp = combineReducers(reducers)
const store = createStore(
todoApp,
// applyMiddleware()
// 告诉 createStore() 如何处理 middlewares
applyMiddleware(logger, crashReporter)
)
以上,就是所有内容了,我们讲了什么是中间件,并手动实现了一个简单的中间件,大家如果对中间件感兴趣,也可以再详细了解下。
如果大家觉得还不错,欢迎给理想哥一个关注,万分感谢大家