本文作者:IMWeb EnjoyChan 原文出处:IMWeb社区 未经同意,禁止转载
项目中使用redux-thunk来解决异步请求的问题,但是为什么要引入redux-thunk来解决异步请求问题,不借助redux-thunk就无法解决吗?
代码语言:javascript复制以setTimeout dispatch场景为例,在异步执行时dispatch action就可以实现了
// 1
store.dispatch({
type: 'BEFORE_ASYNC'
})
setTimeout(() => {
store.dispatch({
type: 'DOING_ASYNC'
})
}, 0)
既然可以简单两步解决,那么为什么还需要引入redux-thunk, 或者说redux-thunk可以解决什么场景问题;来看下面这个场景,我们上面那份代码可能被多次调用,根据传入参数来执行,于是我们封装一个函数:
代码语言:javascript复制// 2
function encapsulateFunc(dispatch, data) {
dispatch({
type: 'BEFORE_ASYNC'
})
setTimeout(() => {
dispatch({
type: 'DOING_ASYNC',
data
})
}, 0)
}
// 调用
encapsulateFunc(store.dispatch, {data: '2'});
第二种
代码语言:javascript复制// 3
// 传入依赖
import store from './store';
function encapsulateFunc(data) {
store.dispatch({
type: 'BEFORE_ASYNC'
})
setTimeout(() => {
store.dispatch({
type: 'DOING_ASYNC',
data
})
}, 0)
}
// 调用
encapsulateFunc({data: '3'});
对比上面封装函数的两种方法我们可以看出:
- 第一种方法, 每次调用的时候都传入dispatch参数,十分冗余
- 第二种方法,植入store依赖,方法依赖于store,这使得代码的迁移性并不友好
鉴于上述,我们再来看看使用redux-thunk,我们可以如何实现
代码语言:javascript复制function encapsulateFunc(data) {
return (dispatch) => {
dispatch({
type: 'BEFORE_ASYNC'
})
setTimeout(() => {
dispatch({
type: 'DOING_ASYNC',
data
})
}, 0)
}
}
store.dispatch(encapsulateFunc({data: '4'}))
ecncapsulateFunc是一个action creator,不需要关心同步还是异步,返回的是对象还是函数,只需要关注传入的参数; 观察ecncapsulateFunc,我们会发现它返回了一个函数,参数传入dispatch,我们称ecncapsulateFunc为thunk函数,关于thunk不了解的可以戳链接http://www.ruanyifeng.com/blog/2015/05/thunk.html;
对比上述,使用redux-thunk可以帮助我们代码更优雅,封装设计更合理,当然redux-thunk是在我们需要的时候才引入,如果我们的实际项目明明可以简单解决,就不需要引入redux-thunk了。
middleware与store enhancer
redux-thunk是一个redux middleware,redux引入middleware方式如下:
代码语言:javascript复制import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import reducer from './reducer';
const middleware = applyMiddleware(thunkMiddleware);
const store = createStore(
reducer,
window.initialState,
middleware
)
将applyMiddlewarer方法执行的返回结果传入createStore第三个参数,那么applyMiddleware方法执行后返回了什么呢,查看redux官方文档,看到createStore的使用如下:
createStore(reducer, [preloadedState], [enhancer])
第三个参数enhancer可选,也就是说applyMiddleware方法返回了一个enhancer,这里的enhancer就是store enhancer, 所谓的enhancer就是增强原有的功能,正如middleware, redux-thunk通过包裹改造dispatch, 使得dispatch方法可以接受函数类型的参数,增强了dispatch的功能;而store,我们知道store有四个属性方法dispatch、getState、subscribe、replaceReducer,通过改造增强这些方法 ,也就可以enhance store, 一个store enhancer大概长这样:
代码语言:javascript复制function storeEnhancerCreator() {
return createStore => (reducer, initialState, enchancer) => {
var store = createStore(reducer, initialState);
// do somethiing to enhance store here
return store;
}
}
基本上拓展功能使用middleware, 但如果有些场景需要改造store,可以试试通过创建一个store enhancer。