越来越忙碌的一周过去了,又到了开始每周总结回顾的时候了。今天就来分析下GitHubredux-thunk这个拥有15.1kstar的开源项目。作为React方向的前端工程师,不管是面试还是面试别人,大部分都会讲到redux-thunk的实现原理,因为非常经典好用,而且代码量非常大小,只有12行代码,但是可以解决React开发中同一个函数支持多个dispatch和异步action的问题(虽然这完全依赖于redux的中间件机制(Middleware))。接下来,笔者将从Redux的工作机制、中间件实现原理、redux-thunk源码实现三个方面,带大家彻底掌握redux-thunk源码,从而对redux有更深入的理解和应用。对react-redux-redux-thunk实战感兴趣的小伙伴,看完可以移步作者的《彻底掌握redux》开发一个任务管理平台。在解读Redux-thunk源码之前,我们需要先掌握基本的工作机制和Middleware实现原理,才能更好地理解源码背后的玄机。长话短说,我们先来看看redux的几个核心API及其作用:redux真正解决的问题是React组件之间的状态共享和状态管理问题。通过以上六大核心API,我们可以管理复杂的状态,可以监听和跟踪状态变化。作者将机制总结如下:基本了解了redux的工作机制后,我们来看一个实际的例子:importactionTypefrom'./actionType'classActions{staticstart(){return{type:actionType.CREATE_TODO_DOING}}statok(数据,cb){cb&&'function'===typeofcb&&cb(数据);返回{type:actionType.CREATE_TODO_SUCCESS,payload:data}}staticfail(数据,cb){cb&&'function'===typeofcb&&cb(数据);return{type:actionType.CREATE_TODO_FAILURE,payload:data}}}从上面的代码可以看出,我们使用了统一的createAction来创建action。调用时,我们只需要执行Actions.start()即可。我们也知道动作返回一个标准对象,但是我们可以在返回之前做一些副作用。这里我们不能在action中处理异步逻辑,这也是redux-thunk的价值之一,就是解决异步调用action。至此,我们还是不能直接进入redux-thunk的源码分析,因为我们还不知道如何解决上面的步骤,因为我们还没有了解redux的中间件机制。redux中间件机制说到中间件(middleware),用过nodejs的人可能都不陌生,比如大家熟知的koa中间件,express中间件等。其实笔者对中间件的理解是在某个executionflow在这个环节做一些额外处理的模块。实现中间件的机制也很简单,就是在框架的核心执行流程中遍历外部传入的中间件,依次执行。我们先来看看redux中如何使用中间件:import{createStore,applyMiddleware}from'redux';importreducersfrom'./reducers';constmiddlewares=applyMiddleware(middleware1,middleware2);conststore=createStore(reducers,middlewares);所以redux-thunk是作为参数传入applyMiddleware方法的,不难猜到在applyMiddleware方法中,一定有遍历执行参数的逻辑。我们看一下applyMiddleware的核心源码:('这里省略N个字符...')}constmiddlewareAPI={getState:store.getState,dispatch:(...args)=>dispatch(...args)}constchain=middlewares.map(function(middleware){returnmiddleware(middlewareAPI)})dispatch=compose(...chain)(store.dispatch)return{...store,dispatch,}}}}从上面的源码中,在chain的代码中,我们发现将applyMiddleware方法参数传入getState并派发后,存储调用结果。接下来,compose函数出现在dispatch的代码中。熟悉函数式编程的朋友不难猜到,它的内部一定是一个实现批链的函数,store.dispatch被泵入其中。经过上面的源码分析,我们知道dispatch的每一次执行,都会先经过中间件的“洗礼”。我们来看看compose函数的内部实现:exportdefaultfunctioncompose(...funcs){if(funcs.length===0){returnarg=>arg}if(funcs.length===1){returnfuncs[0]}returnfuncs.reduce(function(a,b){returnfunction(...args){returna(b(...args))}})}从上面的代码可以看出,compose最后返回了一个函数,如果参数大于一段时间,我们使用reduce将上一个函数返回的结果传递给下一个函数参数,从而实现它们之间参数的共享和传递,这是一个非常经典的设计。掌握了redux中间件的实现原理之后,再看redux-thunk的源码就非常容易理解了。redux-thunk源码分析先看github中15.1kstar的源码:functioncreateThunkMiddleware(extraArgument){return({dispatch,getState})=>(next)=>(action)=>{if(typeofaction==='function'){returnaction(dispatch,getState,extraArgument);}returnext(action);};}constthunk=createThunkMiddleware();thunk.withExtraArgument=createThunkMiddleware;exportdefaultthunk;是的,这都是redux-thunk的来源代码来了,是不是很不错~。在上面的介绍中,我们了解到redux的中间件机制可以让我们在中间件中获取必要的dispatch和getState,并且在执行前已经调用了两层中间件。这时候我们可以剖析一下createThunkMiddleware,在第一个createThunkMiddleware的第一次调用是在chain阶段,也就是上面的源码分析:所以接下来这里就是第二次调用中的store.dispatch。为了在同一个函数中实现多次dispatch,我们会判断如果action是一个函数,那么就执行这个action本身,并给它传递必要的参数,否则直接触发dispatch,这样我们就实现了功能支持作为功能的动作并支持异步多重分派。读到这里,我仍然对其设计的优雅和简洁印象深刻。让笔者感叹:学好函数式风格,走遍天下都不怕!最后笔者准备了一个基于React+redux+redux-thunk的实战项目,github地址:https://github.com/MrXujiang/redux_OA有兴趣的可以学习,仅供参考。最后,如果你想学习更多H5游戏、webpack、node、gulp、css3、javascript、nodeJS、canvas数据可视化等前端知识和实战,欢迎加入我们公众号技术群《趣谈前端》一起学习讨论,一起探索前端。边界。本文转载自微信公众号“趣话前端”,可通过以下二维码关注。转载本文请联系前端公众号。
