当前位置: 首页 > 文档资料 > Redux 简短教程 >

章节 7 - dispatch async action 1

优质
小牛编辑
128浏览
2023-12-01

在上节教程中我们知道了如何分发 action 以及这些 action 如何通过 reducer 函数修改应用状态。

但是,到目前为止,我们只考虑了一种情况,同步场景下的 action,准确地说是同步 action creator,它创建同步的 action,也就是当 action creator 被调用时,action 会被立即返回。

我们来设想一个简单的异步场景:

  1. 用户点击“Say Hi in 2 seconds”按钮
  2. 当用户点击按钮 A,我们希望经过两秒,视图显示一条消息 Hi
  3. 两秒过去之后,更新视图,显示消息 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 函数很可能不知道如何处理这样的返回值,而你也并不清楚是否可行,那么让我们一起再做尝试,一探究竟。