一、redux的异步处理
像vuex提供了异步处理的过程actions,但在redux抛发后直接就让reducer进行处理修改store,貌似并关于异步的处理
但是redux提供了一个非常优秀的机制,中间件,中间件放在事件抛发与事件接收之间,添加了一层拦截,他通过抛发的参数进行一些处理,最后将结果再次抛发出去。
redux-thunk
他是一个专门处理redux异步的中间件
他的结构是四层的闭包函数,运用柯里化思想,第一层用于传入默认值,第二层传入store,可以解构出dispatch、getState,第三层是一个next参数是个特殊的dispatch,他会跳过中间件的拦截放行action,第四层返回的是传入的action
源码解析
es5写法
const setThunk = function (defaule) { //第一层用于传入中间件默认值
return function ({getState,dispatch}) { //store
return function (next) { //next是一个特殊的diapatch,他会跳过中间件的拦截
return function (action) { //action是dispatch传入的参数
if (typeof action === "function") { //判断如果传入的是一个函数则执行这个函数
action(dispatch,getState,defaule)
}else { // 如果传入的是一个对象将放行
next(action)
}
}
}
}
}
const thunk = setThunk(); // 第一层函数不是中间件的逻辑而是redux-thunk想要让中间件能够进行默认值设置而添加的
thunk.setDefaultPayLoad = setThunk //通过setDefaultPayLoad方法来设置默认的参数,让中间件内部能够调用
module.exports = thunk;
es6写法
使用箭头函数能够避免这种嵌套地狱,简化代码
const setThunk = (defaule) => ({getState,dispatch}) => next => action => {
if (typeof action === "function") {
action(dispatch,getState,defaule)
}else {
next(action)
}
}
...
用法
const { createGoods ,createGoodsAsync } = require("./modules/m1/actionCreate"); //引入异步action
const reduxThunk = require("redux-thunk"); //commonjs规范导入要使用reduxThunk.default来调用到入口函数
const store = createStore(reducer,applyMiddleware(reduxThunk.default));
store.dispatch(createGoodsAsync("你好")); //抛发这个异步action
异步action定义
异步action返回的不是一个扁平对象,而是一个异步函数,函数是不符合redux的action规范的,但是他被中间件拦截下来中间件拦截后会执行这个异步函数,当这个异步函数完成后会再次抛发一个对象,这时候中间件会放行,完成了一次异步请求
const fulfill = (msg) => { //将对象返回方法抽离
return {
type:"add",
msg
}
}
const createGoodsAsync = (msg) => { //传入的载荷会被柯里化存储
return ((dispatch,getState,defaultPayLoad) => { //redux-thunk调用方法时会传入dispatch、getState、与中间件的默认值
setTimeout(() => { //异步函数处理
dispatch(fulfill(msg)) //在异步函数执行完成后在去抛发一个对象,这是最终想要的对象
},2000)
})
}
二、中间件
借助redux-thunk的中间件思想来总结一下applyMiddleware这个方法
applyMiddleware的机制
applyMiddleware将多个中间件放在了一个调用链中,也就是层层的调用,通过上一个中间件的next调用到下一个函数,这样后面的中间件可以通过action获取前面中间件处理的内容,通过一层层中间件的调用来达到最终的action,来通知reducer更改state
自定义中间件
const duger = ({getState,dispatch}) => next => action => { //判断的逻辑
if (typeof action === "function") {
action(dispatch,getState,defaule)
}else {
next(action)
}
}
module.exports = duger;
这种中间件提供了异步函数的处理功能,如果想要添加自定义参数功能可以在外层再添加一层柯里化