thunk的概念
A thunk is a function that wraps an expression to delay its evaluation.
-
thunk
是一种函数,他包裹着一个表达式,让这个表达式延迟他的计算。 -
call-by-value
call-by-reference
call-by-name
惰性求值
// 立即计算 1+2 这个表达式的值
// x === 3
let x = 1 + 2;
// 计算 1 + 2 这个表达式的过程被延迟了
// 可以在随后的任意时刻来调用foo 来计算 1+2 的值
// foo 就是一个 thunk
let foo = () => 1 + 2;
const hypot = (x, y) => Math.sqrt(x * x + y * y);
// 'thunk' 是一个没有参数的函数, 当他被调用的时候,执行一些昂贵的操作 或者产生一些 `side-effect`
// 这里不用thunk的话,就已经计算得到5了
const thunk = () => hypot(3, 4);
// 然后这个 thunk 就能被当成参数被传递
doSomethingWithThunk(thunk);
// 或者被调用,这时候才被计算,得到5
thunk(); // === 5
PS:thunk
这个术语(term) 来源于think
这个单词的一种幽默的过去式
为什么要用 redux thunk
Redux
深受函数式编程的影响,创造性的不支持副作用的执行。
尤其是 reducer
, 必须 是符合 (state, action) => newState 的纯函数。
然而, Redux Thunk
能拦截分发的 action
并添加额外的复杂行为,还可以添加副作用。
这样就能用更为复杂或者异步的逻辑书写 action 创建函数
。
类似作用的中间件还有Redux Saga
、 Redux Loop
等
Github 关于redux-thunk的介绍
With a plain basic Redux store, you can only do simple synchronous updates by dispatching an action. Middleware extend the store's abilities, and let you write async logic that interacts with the store.
-
store
存储着应用的所有状,如果你仅仅使用redux
的基本的store
,你只能通过dispatch action
来做一些同步的数据更新(和store交互)。但是通过中间件
能扩展store
的能力,让你能写一些异步
的逻辑来和store
进行交互。
Thunks are the recommended middleware for basic Redux side effects logic, including complex synchronous logic that needs access to the store, and simple async logic like AJAX requests.
-
Thunks
是使redux
能够使用副作用
相关的逻辑的一种推荐的中间件
。比如很复杂的需要和store
交互的同步
逻辑、或者简单的AJAX
请求的异步
逻辑。
Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods
dispatch
andgetState
as parameters.
-
redux thunk
中间件允许你写的action creators
返回一个function
,而不是一个action
。thunk
能延迟dispatch
一个action
,或者说只有特定条件发生的时候才dispatch
一个action
。(很明显很适合AJAX
请求,当得到数据返回时,再发出action
)
总结
不使用 redux-thunk
时,如果在异步请求中使用redux,要发出三个action
function loadData(dispatch, userId) { // needs to dispatch, so it is first argument
dispatch({type: 'START'}); // 异步开始时发出一个
return fetch(`http://data.com/${userId}`)
.then(response => response.json())
.then(json => dispatch({type: 'SUCCESS', payload: json}))
.catch(err => dispatch({type:'FAILE',payload: err}))
};
};
componentDidMount() {
loadData(this.props.dispatch, this.props.userId); // don't forget to pass dispatch
}
如上, 发起这个异步请求是调用loadData()
函数,在loadData函数里,会在合适的时机发出合适的action
。
而使用 redux-thunk
时 ,发起异步请求是dispatch
一个函数 —— 调用 loadData()
返回的一个函数,然后再发出具体的action
对象。而普通的 Action Creator 默认返回一个对象。
也就是说,使用redux-thunk
中间件,改造了 store.dispatch
,使得后者可以接受函数作为参数,而这个函数的功能就是在合适的时机发出三个action
这么做的好处是,不必在componentDidMount
里写一堆网络请求相关的代码了
// action creator
loadData = userId => (dispatch, getState) => {
fetch(`http://data.com/${userId}`) // Redux Thunk handles these
.then(res => res.json())
.then(
data => dispatch({ type: 'LOAD_DATA_SUCCESS', data })
)
.catch(
err => dispatch({ type: 'LOAD_DATA_FAILURE', err })
)
}
componentDidMount() {
this.props.dispatch(loadData(this.props.userId)); // dispatch like you usually do
}
总结来说,redux-thunk
的作用就是让redux
的 store.dispatch
能接受函数作为参数,然后你就可以发挥你的想象来写这个函数的功能,完成一些你需要的功能。
网友评论