Open Juliiii opened 5 years ago
最近刚把redux的源码阅读放了上来,那么再接再厉,咱们来看个redux中间件的源码,随便学习下怎么写个redux的中间件。额,为了简单点,所以选了redux-thunk。redux-thunk是什么?用过的同学应该知道是,redux处理异步action的一个中间件。然而他的源码也非常简单,不到20行,就完全可以实现处理异步action的需求,再一次感叹大牛的奇思妙想。
小二,上代码!
const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
先看看它的导出,哦,是先执行了createThunkMiddleware 这个函数,得到一个返回值,并将返回值赋值给thunk,并同时将这个函数挂载在thunk 上。最后导出给用户使用。那createThunkMiddleware 就是我们要剖析的核心了。下面为代码:
createThunkMiddleware
thunk
function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; }
这个函数,接受extraArgument 作为参数,并返回一个函数,而这个函数就是我们之前聊redux时,说到中间件的写法。就是形如 store => next => action => {}。所以这个函数会返回一个中间件给我们。而这个中间件,会判断action是不是function,如果是,就传入dispatch,getState等,执行,并返回;如果不是,就过,传给下一个中间件 。好了,redux-thunk的原理就这么简单。哈哈哈哈哈,额。为了避免有的同学没用过redux-thunk,那下面结合一个例子来讲解为毛原理就这么简单 。
extraArgument
async function getUserInfo(dispatch, getState, userId) { try { const user = await axios.get(`/users/${userId}`); dispatch({ type: 'GETUSERINFO_SUCCESS', data: user }); } catch(e) { dispatch({ type: 'GETUSERINFO_FAILED', error: e }); } } store.dispatch(getUserInfo);
redux-thunk的用法,如果我没记错,应该是这么用(毕竟一直用redux-saga),正常的dispatch是接受一个简单对象的。但是redux-thunk允许我们传入一个函数,这个函数就是一个异步操作的函数。redux-thunk检测到是个函数的时候,就会执行该函数。函数会做异步操作。在未来的某个时间点,异步操作完成,会根据成功或者失败,去dispatch不同的action,而这次dispatch的action就是一个正常的action,即为一个简单对象,和正常使用redux的效果是一样的。所以,大家明白了redux的内部原理了吧。
那么看了上面,懂得写一个中间件的套路了吗?
看了redux和redux-thunk的源码后,我个人总结出一个redux的中间件应该具备以下两点
第一点是因为,在redux的applyMiddleware中,对于中间件的处理,是先传入一个middlewareAPI,这个API包含了两样东西,一个是store.getState,一个是增强过的dispatch。然后得到一个形如 next => action => {} 的数组。然后对于这个数组,才有compose函数来处理,另其变成 (...args) => f(g(h(...args)))的一个函数。再然后再传入一个store.dispatch,这个函数就会执行,然后这个数组的函数就会从右往左执行,最后得到第一个action => {}的函数。当dispatch的时候,这个函数被执行,由于这个函数内调用了 next(action),所以中间件们就会以一种链式的结构被执行。所以个中间件只要具备以上两点,个人觉得就可以了。举了例子
const logger = store => next => action => { console.log('currentState: ', store.getState()); let result = next(action) console.log('nextState', store.getState()); return result }
这就是一个logger的中间件了,咱们看下效果:
这次也到这里了,这次篇幅不多,难度不难。大家也可以自行看看源码。老规矩,源码地址:https://github.com/Juliiii/source-plan 欢迎大家star或者fork ,也可以和我讨论学习 。
围观朱理大佬
手动滑鸡
背景
最近刚把redux的源码阅读放了上来,那么再接再厉,咱们来看个redux中间件的源码,随便学习下怎么写个redux的中间件。额,为了简单点,所以选了redux-thunk。redux-thunk是什么?用过的同学应该知道是,redux处理异步action的一个中间件。然而他的源码也非常简单,不到20行,就完全可以实现处理异步action的需求,再一次感叹大牛的奇思妙想。
开始
小二,上代码!
先看看它的导出,哦,是先执行了
createThunkMiddleware
这个函数,得到一个返回值,并将返回值赋值给thunk
,并同时将这个函数挂载在thunk
上。最后导出给用户使用。那createThunkMiddleware
就是我们要剖析的核心了。下面为代码:这个函数,接受
extraArgument
作为参数,并返回一个函数,而这个函数就是我们之前聊redux时,说到中间件的写法。就是形如 store => next => action => {}。所以这个函数会返回一个中间件给我们。而这个中间件,会判断action是不是function,如果是,就传入dispatch,getState等,执行,并返回;如果不是,就过,传给下一个中间件 。好了,redux-thunk的原理就这么简单。哈哈哈哈哈,额。为了避免有的同学没用过redux-thunk,那下面结合一个例子来讲解为毛原理就这么简单 。
redux-thunk的用法,如果我没记错,应该是这么用(毕竟一直用redux-saga),正常的dispatch是接受一个简单对象的。但是redux-thunk允许我们传入一个函数,这个函数就是一个异步操作的函数。redux-thunk检测到是个函数的时候,就会执行该函数。函数会做异步操作。在未来的某个时间点,异步操作完成,会根据成功或者失败,去dispatch不同的action,而这次dispatch的action就是一个正常的action,即为一个简单对象,和正常使用redux的效果是一样的。所以,大家明白了redux的内部原理了吧。
那么看了上面,懂得写一个中间件的套路了吗?
看了redux和redux-thunk的源码后,我个人总结出一个redux的中间件应该具备以下两点
第一点是因为,在redux的applyMiddleware中,对于中间件的处理,是先传入一个middlewareAPI,这个API包含了两样东西,一个是store.getState,一个是增强过的dispatch。然后得到一个形如 next => action => {} 的数组。然后对于这个数组,才有compose函数来处理,另其变成 (...args) => f(g(h(...args)))的一个函数。再然后再传入一个store.dispatch,这个函数就会执行,然后这个数组的函数就会从右往左执行,最后得到第一个action => {}的函数。当dispatch的时候,这个函数被执行,由于这个函数内调用了 next(action),所以中间件们就会以一种链式的结构被执行。所以个中间件只要具备以上两点,个人觉得就可以了。举了例子
这就是一个logger的中间件了,咱们看下效果:
结语
这次也到这里了,这次篇幅不多,难度不难。大家也可以自行看看源码。老规矩,源码地址:https://github.com/Juliiii/source-plan 欢迎大家star或者fork ,也可以和我讨论学习 。