Appearance
级联中间件
本节目标:理解“级联中间件”的核心思路,并能把它用于实际开发或面试表达。
说明:原 OneNote 中有图片引用,但图片未包含在导出目录中;本页保留了可用的文字与代码内容。 目录划分:
- 仓库
store - 状态管理工具:
redux react状态管理工具:react-redux
修改
src/store/index.js
import{
createStore,applyMiddleware } from
'../redux';
importrootReducer from
'./reducers';
importpromise from
'../redux-promise';
importlogger from
'../redux-logger';
importthunk from
'../redux-thunk';
letstore =
applyMiddleware(thunk,promise,logger)(createStore)(rootReducer);
exportdefault
store;这里的store,我们通过applyMiddleware源码了解,这个store包含了我们应用了中间件后的dispatch,和子store;
Promise thunk使用Src/store/actions/couter1.js中添加一个
action;
promiseAdd(){return new
Promise((resolve,reject)=\> {/* fetch('/user.json').then(res=\>res.json()).then(res=\>{resolve({type:actionTypes.ADD1});});; */
setTimeout(()=\> {let number =
Math.random(); `if`
(number\>=
.5){
resolve({type:
actionTypes.ADD1});} else {
resolve({type:
actionTypes.ADD1});}},
1000);});
},新建
src/redux-promise.js
/*** dispatch 重新派发 * next 下一步 * @param {*} param0* @returns
*/
functionpromise({getState,dispatch }) {return function
(next){//调用下一个中间件 next=store.原始的dispatch方法 return function
(action){//这个就是改造后的dispatchif
(action.then&& typeof
action.then===
'function'){
action.then(dispatch).catch(dispatch); `}` `else` `if`
(action.payload&& typeof
action.payload.then===
'function'){
action.payload.then(payload=\>
dispatch({...action,payload }))
.catch(error=\> {
dispatch({...action,error:
true,payload: error });return
Promise.reject(error); `})`
`}` `else` `{`
next(action); `}`
`}`
}
}
exportdefault
promise;在src/components/counter.js中添加一个按钮:
<buttononClick={thunkAdd}>thunkAdd</button>
<buttononClick={promiseAdd}>promiseAdd</button>添加另外一种promise实现,之前返回一个函数的方式只能处理成功情况,不能处理失败情况;
Src/store/actions/counter1.js
promise2Add(){return {type:
actionTypes.ADD1, `payload:` `new`
Promise((resolve,reject)=\> {
setTimeout(()=\> {let number =
Math.random(); `if`
(number\>=
.5){
resolve(1); `}` `else` `{`
reject('失败了
'); `}`
`},`
1000); `})`
}
}在src/redux-promise.js,添加处理 /*** dispatch ==重新派发== * next ==下一步== * @param {*} param0* @returns
*/
functionpromise({getState,dispatch }) {return function
(next){//调用下一个中间件 next=store.原始的dispatch方法 return function
(action){//这个就是改造后的dispatchif
(action.then&& typeof
action.then===
'function'){
action.then(dispatch).catch(dispatch); `}` `else` `if`
(action.payload&& typeof
action.payload.then===
'function'){
action.payload.then(payload=\>
dispatch({...action,payload }))
.catch(error=\> {
dispatch({...action,error:
true,payload: error });return
Promise.reject(error); `})`
`}` `else` `{`
next(action); `}`
`}`
}
}
exportdefault
promise;src\redux-thunk\index.js
functionthunk({getState,dispatch }) {return function
(next){//调用下一个中间件 next=store.原始的dispatch方法 return function
(action){//这个就是改造后的dispatchdebuggerif
(typeofaction ===
'function'){return
action(dispatch,getState); `}`
`return`
next(action);//next=store.dispatch `}`
}
}
exportdefault
thunk;Src/actions/conuter1.js
import* as actionTypes from
'../action-types';
letactions = {
add1(){return { type:
actionTypes.ADD1};},
minus1(){return { type:
actionTypes.MINUS1};},
changeColor(color){return { type:
actionTypes.CHANGE_COLOR,payload: color };},
thunkAdd(){return function
(dispatch,getState){
setTimeout(()=\> {
dispatch(newPromise((resolve,reject)=\> {
setTimeout(()=\> {let number =
Math.random(); `if`
(number\>=
.5){
resolve({type:
actionTypes.ADD1});} else {
resolve({type:
actionTypes.ADD1});}},
1000); `}));`
`},`
1000); `}`
},
promiseAdd(){return new
Promise((resolve,reject)=\> {/* fetch('/user.json').then(res=\>res.json()).then(res=\>{resolve({type:actionTypes.ADD1});});; */
setTimeout(()=\> {let number =
Math.random(); `if`
(number\>=
.5){
resolve({type:
actionTypes.ADD1});} else {
resolve({type:
actionTypes.ADD1});}},
1000); `});`
},
promise2Add(){return {type:
actionTypes.ADD1, `payload:` `new`
Promise((resolve,reject)=\> {
setTimeout(()=\> {let number =
Math.random(); `if`
(number\>=
.5){
resolve(1); `}` `else` `{`
reject('失败了
'); `}`
`},`
1000); `})`
`}`
}
}
exportdefault
actions;Src/store/index.js
import{
createStore,applyMiddleware } from
'../redux';
importrootReducer from
'./reducers';
importpromise from
'../redux-promise';
importlogger from
'../redux-logger';
importthunk from
'../redux-thunk';
letstore =
applyMiddleware(thunk,promise,logger)(createStore)(rootReducer);
exportdefault
store;修改
src/store/reducers/counter1.js
importReact,{ Component } from
'react'
import{ connect } from
'../react-redux';
importactions from
'../store/actions/counter1';
import* as actionTypes from
'../store/action-types';
//Counter1.props=
{...state.counter1,...actions};
classCounter1 extends Component {
render(){let {
color,number,add1,minus1,changeColor,thunkAdd,promiseAdd, `promise2Add`
`}` `=`
this.props; `return` `(`
<divstyle={{color
}}><p>{number}</p><buttononClick={add1}>+</button><buttononClick={minus1}>-</button><buttononClick={()=\>
changeColor('red')}>改成红色
</button><buttononClick={thunkAdd}>thunkAdd</button><buttononClick={promiseAdd}>promiseAdd</button><buttononClick={promise2Add}>promise2Add</button></div> `)`
}
}
//把仓库中的状态映射为组件的属性对象 输入 let mapStateToProps = state =\>
state.counter1;
//把dispatch方法映射为一个属性对象 let mapDispatchToProps = dispath =\> ({
add1(){
dispath({type:
actionTypes.ADD1});},
minus1(){
dispath({type:
actionTypes.MINUS1});},
changeColor(color){
dispath({type:
actionTypes.CHANGE_COLOR,payload: color });
}
})
//把派发的动作映射为属性对象 //let
mapDispatchToProps
exportdefault
connect(mapStateToProps,//mapDispatchToProps //第一种 actions //第二种
)(Counter1);
/*** 组件关联仓库两个方向 * 输入 组件里使用仓库提供的状态进行组件的渲染 * 输出 在组件可以派发动作从而修改仓库中的状态
*/
compose- 如果一个函数需要经过多个函数处理才能得到最终值,这个时候可以把中间过程的函数合并一个函数
;
src\redux\compose.js
compose
function
add1(str){return '1' +
str;
}
functionadd2(str){return '2' +
str;
}
functionadd3(str){return '3' +
str;
}
functioncompose(...funcs){return function
(args){for
(leti =
funcs.length-
1;i \>=
0;i--){args =
funcs[i](args); `}`
`return`
args;}
}
functioncompose(...funcs){return
funcs.reduce((a,b)=\>
(...args)=\>
a(b(...args)));
}
/**
*第一次 a=add3 b=add2 =\>
(...args)=>add3(add2(...args))
*第二次 a=(...args)=\>add3(add2(...args)) b=add1 =\>
(...args)=>add3(add2((add1(...args)))))
*/letfn =
compose(add3,add2,add1);
letresult =
fn('zhufeng');
console.log(result);链式调用
functioncompose(...funcs){return
funcs.reduce((a,b)=\>
(...args)=\>
a(b(...args)));
}
letpromise =
(next)=\> action =\> {
console.log('promise');next(action);
};
letthunk =
(next)=\> action =\> {
console.log('thunk');next(action);
};
letlogger =
(next)=\> action =\> {
console.log('logger');next(action);
};
letchain =
[promise,thunk,logger];
letcomposed =
compose(...chain)
letdispatch = () =\> {
console.log('原始的
dispatch');
}
letnewDispatch =
composed(dispatch);
newDispatch({type: "add" });
