Q:为什么我们无法直接进行数据请求?
Redux store 对异步逻辑一无所知。它只知道如何同步 dispatch action,通过调用 root reducer 函数更新状态,并通知 UI 某些事情发生了变化。任何异步都必须发生在 store 之外。但是,如果你希望通过调度或检查当前 store 状态来使异步逻辑与 store 交互,该怎么办?
A:使用中间件
Redux middleware 扩展了 store,允许我们
dispatch action
时执行额外的逻辑- 暂停、修改、延迟、替换或停止
dispatch
的action
- 编写可以访问
dispatch
和getState
的额外代码 - 在使用中间件之前,
dispatch
的action
只能是对象,在使用中间件之后,dispatch
的action
可以是函数也可以是promise
我们常用的处理异步的中间件是redux-thunk
为什么是 redux-thunk
他仅仅是让dispath
多支持了一种类型,就是函数类型,在使用Redux-Thunk
前我们dispatch
的action
必须是一个纯对象(plain object
),使用了Redux-Thunk
后,dispatch
可以支持函数,这个函数会传入dispatch
本身作为参数。
一些对比:
- Thunks 最适合复杂的同步逻辑(尤其是需要访问整个 Redux store state 的代码)和简单的异步逻辑(如基本的 AJAX 调用)。通过使用
async/await
,将 thunk 用于一些更复杂的基于 Promise 的逻辑也是合理的。 - Sagas 最适合复杂的异步逻辑和解耦的 "background thread" 类型的行为,特别是如果你需要监听已 dispatch 过的 action(这是 thunk 无法完成的事情)。需要熟悉 ES6 生成器函数和
redux-saga
的 "effects" 运算符。 - Observables 解决了与 sagas 相同的问题,但依赖 RxJS 来实现异步行为。需要熟悉 RxJS API。
增加 redux-thunk 之后的数据流

一些 Demo
- 在没有使用
Redux-thunk
的时候
JavaScript
function increment() {
return {
type: 'INCREMENT'
}
};
store.dispatch(increment());
- 在使用
Redux-thunk
之后
JavaScript
function increment() {
return {
type: 'INCREMENT'
}
};
// 异步action creator
function incrementAsync() {
return (dispatch) => {
setTimeout(() => {
dispatch(increment());
}, 1000);
}
}
// 使用了Redux-Thunk后dispatch不仅仅可以发出plain object,还可以发出这个异步的函数
store.dispatch(incrementAsync());
不用 Redux-thunk 是否解决问题?
如果你想用JS处理一个延时任务,直接用
setTimeout
就好了,即使你使用了Redux
也没啥区别。Redux
确实提供了另一种处理异步任务的机制,但是你应该用它来解决你很多重复代码的问题。如果你没有太多重复代码,使用语言原生方案其实是最简单的方案。
JS
store.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
store.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)
关于这个问题,这里有更为详细的解答:异步方案对比
那么这就是本篇文章的全部内容啦~