章节 7 - dispatch async action 1
优质
小牛编辑
132浏览
2023-12-01
在上节教程中我们知道了如何分发 action 以及这些 action 如何通过 reducer 函数修改应用状态。
但是,到目前为止,我们只考虑了一种情况,同步场景下的 action,准确地说是同步 action creator,它创建同步的 action,也就是当 action creator 被调用时,action 会被立即返回。
我们来设想一个简单的异步场景:
- 用户点击“Say Hi in 2 seconds”按钮
- 当用户点击按钮 A,我们希望经过两秒,视图显示一条消息 Hi
- 两秒过去之后,更新视图,显示消息 Hi
当然这条消息是应用的状态之一,所以我们必然将其存储于 Redux store。
但是我们希望的结果是,在调用 action creator 的两秒之后才把消息存入 store(因为如果立即更新状态,那么就会立即触发所有监听状态变更的订阅者 —— 例如视图,导致消息早于两秒显示)。
如果我们按照目前调用 action creator 的方式...
import { createStore, combineReducers } from 'redux' var reducer = combineReducers({ speaker: function (state = {}, action) { console.log('speaker was called with state', state, 'and action', action) switch (action.type) { case 'SAY': return { ...state, message: action.message } default: return state; } } }) var store_0 = createStore(reducer) var sayActionCreator = function (message) { return { type: 'SAY', message } } console.log("\n", 'Running our normal action creator:', "\n") console.log(new Date()); store_0.dispatch(sayActionCreator('Hi')) console.log(new Date()); console.log('store_0 state after action SAY:', store_0.getState())
// 输出(忽略初始输出): // Sun Aug 02 2015 01:03:05 GMT+0200 (CEST) // speaker was called with state {} and action { type: 'SAY', message: 'Hi' } // Sun Aug 02 2015 01:03:05 GMT+0200 (CEST) // store_0 state after action SAY: { speaker: { message: 'Hi' } }
结果 store 被立即更新了。
我们希望看到的结果应该类似于下面这样的代码:
var asyncSayActionCreator_0 = function (message) { setTimeout(function () { return { type: 'SAY', message } }, 2000) }
但是这样 action creator 返回的不是 action 而是 undefined。所以这并不是我们所期望的解决方法。
这里有个诀窍:不返回 action,而是返回 function。这个 function 会在合适的时机 dispatch action。但是如果我们希望这个 function 能够 dispatch action,那么就需要向它传入 dispatch 函数。于是代码类似如下:
var asyncSayActionCreator_1 = function (message) { return function (dispatch) { setTimeout(function () { dispatch({ type: 'SAY', message }) }, 2000) } }
你可能再次注意到 action creator 返回的不是 action 而是 function。
所以 reducer 函数很可能不知道如何处理这样的返回值,而你也并不清楚是否可行,那么让我们一起再做尝试,一探究竟。