We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
我们先写一个极简单的createStore函数,省去了与本次文章无关的reducer参数,最初始版本,满足修改数据需求:
reducer
function createStore(initState) { return { dispatch(change) { console.log('origin dispatch'); initState += change; }, getState() { return initState; }, }; }
然后就可以这么用了:
var state = createStore(528); state.dispatch(138); console.log(state.getState()); // 666
兴高采烈完成后,忍不住给自己打 call: 666。
老大:我们需要在dispatch的前后各打印一行日志
dispatch
你想了想,这难不倒我:
var state = createStore(528); console.log('before change'); state.dispatch(138); console.log('after change');
老大,黑人问号??????:我们是大公司,将来我们的代码会有好几十万行,有几千上万个这样的dispatch,你确定要一个个去写?
你: 那我把createStore返回的 dispatch 代码改了吧
createStore
老大:我们 A、B、C 项目不需要打印日志,P、Q、J 需要。
你内心 OS:这老大怕是产品派来的卧底吧。
作为需求压不死的小强,你很快平静了内心:那我加个参数,决定是否打印日志吧。
老大:我们还有TMD项目只需要打印before日志而不需要after日志,我们有MMP项目需要异步产生数据,我们有...,我们还有TNNGT项目既需要 xx 功能也需要 yy 功能...
TMD
before
after
MMP
TNNGT
你:大佬,别说了,别说了,我改,我改还不行么。。。。
看来是时候引入中间件机制了。
思考过程:
initState
所以,我们的代码大概长这样子:
function createStore(initState, middleware) { if (typeof middleware === 'function') { return middleware(createStore(initState)); } return { dispatch(change) { console.log('origin dispatch'); initState += change; }, getState() { return initState; }, }; }
依照我们想象的middleware被调用的样子,我们来实现一个记录日志的middleware:
middleware
function log(store) { function dispatch(change) { console.log('before change'); var ret = store.dispatch(change); console.log('after change'); return ret; } return { ...store, dispatch, }; }
小试一下:
var s = createStore(10, log); s.dispatch(5);
粘贴代码跑一下,你会发现是你预期的样子,成功了一小步,内心配合 OS:我的一小步,确是...
目前可以使用单个中间件了,如果需要同时使用多个中间件的话,我们还得继续思考,中间件的作用是改造原有dispatch,返回新的dispatch,那么,我们需要使用多个中间件的话就得把这些中间件串起来,然后将原来的dispatch作为参数传入:a(b(c(dispatch)))。
a(b(c(dispatch)))
首先我们需要自己实现下compose函数,这样a(b(c(dispatch)))就可以写成compose(a,b,c)(dispatch):
compose
compose(a,b,c)(dispatch)
function compose(...fns) { return fns.reduce((a, b) => (...args) => a(b(...args))); }
然后我们需要一个函数来处理多个中间件串联的情况,串联完成后再将其给到createStore作为第二个参数:
function applyMiddleware(...middlewares) { return function(store) { var dispatch = compose(...middlewares)(dispatch); // ... return { ...store, dispatch, }; }; }
似乎有些问题,我们compose操作后得到的最终dispatch和store.getState无法在各个中间件内部使用, 我们需要将中间件函数变成一个三阶函数,接收{dispatch,getState}作为参数,返回一个函数是以compose的过程中产生的上一个dispatch作为参数的函数,这个函数返回一个新的dispatch,有点绕,我们直接看函数签名:
store.getState
{dispatch,getState}
({dispatch, getState}) => next => action => {}
所以,我们的applyMiddleware需要改造:
applyMiddleware
function applyMiddleware(...middlewares) { return function(store) { var dispatch; var chain = middlewares.map(middleware => middleware({ ...store, // 形成闭包,延时取dispatch dispatch: (...args) => dispatch(...args), }) ); dispatch = compose(...chain)(store.dispatch); return { ...store, dispatch, }; }; }
依据上面的中间件签名,我们重新实现下日志中间件:
function log() { return function(next) { return function(action) { console.log('before dispatch'); var ret = next(action); console.log('after dispatch'); return ret; }; }; }
再实现一个 thunk 中间件:
function thunk({ dispatch }) { return function(next) { return function(action) { if (typeof action === 'function') { return action(dispatch); } return next(action); }; }; }
我们就可以这样用了:
var s = createStore(10, applyMiddleware(log, thunk)); s.dispatch(5); s.dispatch(function() { return 651; });
// TODO 代码继续优化
The text was updated successfully, but these errors were encountered:
No branches or pull requests
我们先写一个极简单的createStore函数,省去了与本次文章无关的
reducer
参数,最初始版本,满足修改数据需求:然后就可以这么用了:
兴高采烈完成后,忍不住给自己打 call: 666。
老大:我们需要在
dispatch
的前后各打印一行日志你想了想,这难不倒我:
老大,黑人问号??????:我们是大公司,将来我们的代码会有好几十万行,有几千上万个这样的
dispatch
,你确定要一个个去写?你: 那我把
createStore
返回的 dispatch 代码改了吧老大:我们 A、B、C 项目不需要打印日志,P、Q、J 需要。
你内心 OS:这老大怕是产品派来的卧底吧。
作为需求压不死的小强,你很快平静了内心:那我加个参数,决定是否打印日志吧。
老大:我们还有
TMD
项目只需要打印before
日志而不需要after
日志,我们有MMP
项目需要异步产生数据,我们有...,我们还有TNNGT
项目既需要 xx 功能也需要 yy 功能...你:大佬,别说了,别说了,我改,我改还不行么。。。。
看来是时候引入中间件机制了。
思考过程:
dispatch
函数dispatch
与initState
createStore
一致,这样我们后续的逻辑就可以复用所以,我们的代码大概长这样子:
依照我们想象的
middleware
被调用的样子,我们来实现一个记录日志的middleware
:小试一下:
粘贴代码跑一下,你会发现是你预期的样子,成功了一小步,内心配合 OS:我的一小步,确是...
目前可以使用单个中间件了,如果需要同时使用多个中间件的话,我们还得继续思考,中间件的作用是改造原有
dispatch
,返回新的dispatch
,那么,我们需要使用多个中间件的话就得把这些中间件串起来,然后将原来的dispatch
作为参数传入:a(b(c(dispatch)))
。首先我们需要自己实现下
compose
函数,这样a(b(c(dispatch)))
就可以写成compose(a,b,c)(dispatch)
:然后我们需要一个函数来处理多个中间件串联的情况,串联完成后再将其给到
createStore
作为第二个参数:似乎有些问题,我们
compose
操作后得到的最终dispatch
和store.getState
无法在各个中间件内部使用,我们需要将中间件函数变成一个三阶函数,接收
{dispatch,getState}
作为参数,返回一个函数是以compose
的过程中产生的上一个dispatch
作为参数的函数,这个函数返回一个新的dispatch
,有点绕,我们直接看函数签名:所以,我们的
applyMiddleware
需要改造:依据上面的中间件签名,我们重新实现下日志中间件:
再实现一个 thunk 中间件:
我们就可以这样用了:
// TODO 代码继续优化
The text was updated successfully, but these errors were encountered: