middleware
redux middlewarwe middleware 提供了一个分类处理 action 的机会,在 middleware 中你可以检阅每一个流过的 action,挑选出特定类型的** action 进行相应操作,给你一次改变 action **的机会。
它提供了位于action被发起之后,reducer到达之前的扩展点。
为什么需要middleware
上图表示的是redux中简单的同步数据流的过程,在view界面触发一个事件后,在后调中dispatch一个action,reducer收到action,更新state并通知view更新。但是如果处理异步action操作 ,这样的方法就不是很好的,单纯的修改 dispatch 或 reducer 的代码显然不具有普世性,我们需要的是可以组合的,自由插拔的插件机制,这一点 redux 借鉴了 koa** 里中间件的思想,koa 是用于构建 web 应用的 NodeJS 框架。另外 reducer 更关心的是数据的转化逻辑,所以 redux 的 middleware 是为了增强 dispatch 而出现的。
redux的middleware用reduceRight方法,将applyMiddleware
方法中的参数串起来,原始的dispatch方法会最后执行。
applyMiddleware的源码及分析
export default function applyMiddleware(...middlewares) {
/**
* 返回值是一个函数,因此在使用的时候是如下形式:
* var store = applyMiddleware(...midlewares)(createStore)(reducer)
*/
return (createStore) => (reducer, initialState, enhancer) => {
// 普通方式创建的store
var store = createStore(reducer, initialState, enhancer)
var dispatch = store.dispatch
var chain = []
/**
* 将store的一部分接口暴露给中间件
* 在编写中间件的时候,通常形式为:
* function middleware(store){
* return next => action => { ... }
* }
* 参数的store其实就是middlewareAPI
*/
var middlewareAPI = {
getState: store.getState,
/**
* 这里之所以使用一个匿名函数,而不是`dispatch: dispatch`的形式
* 是因为在中间件中执行store.dispatch的时候,dispatch的值已经改变
* 在下面的代码中将会看到dispatch被重新赋值
*/
dispatch: (action) => dispatch(action)
}
/**
* chain是一个数组,数组中的每一项都是一个具有如下形式的函数:
* function(next){
* return function(action){ ... }
* }
*/
chain = middlewares.map(middleware => middleware(middlewareAPI))
/**
* 假设chain为[mw1, mw2, mw3]
* 那么此时dispatch为mw1(mw2(mw3(store.dispatch)))
* 即store.dispatch作为mw3的next参数
* mw3(store.dispatch)作为mw2的next参数,以此类推
* 最终的返回值是一个函数,其形式为:
* function(action){ ... }
* 该函数作为新的dispatch(或者说,包装后的dispatch)
*/
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
编写middleware
如果需要自定义middleware也很简单,这个middleware只接收一个action,执行后也需要返回一个action;如果需要执行下一步,调用next(action)即可。
基本使用方式:
store => next => action{
if(action.type === ''){ //找到对应的action.type的名称执行下面的代码
}else{
next(action); //next指向下一个要执行的action
}
}
在项目中使用的具体示例:
//postMessage.js
export default store => next => action =>{
if(action.type === "POSTMESSAGE"){
request.post('/postMessage')
.send({userName:action.data.user,goodName:action.data.name,description:action.data.description,
price:action.data.price,count:action.data.count,telephoneNumber:action.data.telephoneNumber})
.end((err,res)=>{
next({type:"POSTMESSAGE",isSaved:res.body});
})
}else{
next(action);
}
}
//将middleware导出之后,在main函数中调用,通过applyMiddleware将所有的middleware串起来。
//main.js
import React from 'react';
import {render} from "react-dom";
import {createStore, applyMiddleware} from 'redux';
import {Provider} from "react-redux";
import PostMessage from './containers/postMessage';
const createStoreWithMiddleware = applyMiddleware(ResgierMiddleware,LoginMiddleware,NavMiddleware,PostMessageMiddleware)(createStore);