编排多个动作

时间:2016-01-14 21:02:35

标签: javascript redux

我不清楚如何协调Redux中的多个连续动作。例如,我有一个应用程序,左侧有一个摘要面板,右侧有一个CRUD面板。在用户CRUD之后,我希望应用程序自动更新摘要。我还希望能够相互独立地刷新摘要和CRUD。换句话说,我希望CRUD操作必须知道摘要或任何其他未来的下游后续操作(反之亦然)。是否有最佳实践来协调这一点,而不让我的行动创作者知道其他行为?

例如,这里是用于清除实体集合的(thunk)动作创建者(CRUD动作)。是的,现在它与fetchSummary()派遣紧密结合。

export function clearCollection(collection) {
    return function(dispatch) {
        dispatch(requestCollectionClear(collection));

        return doClearCollection(collection)
            .then(function(coll) { 
                dispatch(receiveCollectionCleared(coll))
            })
            .then(function() {
                dispatch(fetchSummary()); // <-- How do I chain actions without tight coupling?
            });
            // TODO: .catch()
    }
}

其中requestCollectionClear()启动异步操作,fetchSummary()是工作流后续步骤的操作创建者。将fetchSummary()clearCollection()分开的最佳模式是什么,将它们分离以便彼此独立使用?

3 个答案:

答案 0 :(得分:1)

如果我在评论中正确理解了您对问题的回答(您的CRUD操作会更新一些收集数据,而您的摘要会显示相同收集数据的某些版本),我认为您可以通过考虑您的问题来解决您的问题申请方式不同。

您的状态应该是具有collections键的对象的行,并且您的reducer应该对此对象进行操作。因此,clearCollections方法会将collections值设置为空数组,fetchCollections方法会将collections值设置为来自服务器的新数据数据等。

然后,您的摘要只会订阅您的store,并显示collections密钥的最新和最大价值。没有更紧密的耦合。

编辑:根据评论,我认为您基本上是在询问如何在服务器和客户端之间就数据进行协调。处理此问题的一种方法是在应用程序加载时从服务器获取收集数据,然后通过调度操作(并将数据传递给操作创建者)将此数据填充到Redux存储中:

// Fetch your data
$.ajax({
  url: '/collections',
  method: 'GET',
  success: function(response) {
    // Populate your Redux store by dispatching an action
    store.dispatch(setCollections(response));
  }
});

然后,当您想要更新数据时,比如添加一个集合,您可以这样做:

// Update the Redux store, which updates the UI.
store.dispatch(addCollection(someNewData));

然后更新服务器,并在响应时进行协调

$.ajax({
  url: '/collections',
  method: 'POST',
  data: {collection: someCollection},
  success: function(response) {
    // Should be a no-op b/c client has already
    // been updated.
    store.dispatch(setCollections(response))
  }
});

您的动作创建者和缩减者将如下所示:

// Action creators:
function setCollections(collections) {
  return {type: 'setCollections', collections: collections}
}

function addCollection(collection) {
  return {type: 'addCollection', collection: collection}
}

// Reducer
function reduceCollections(state = initialState, action) {
  if (action.type === 'setCollections') {
    return {collections: action.collections}

  } else if (action.type === 'addCollection') {
    return {
      collections: state.collections.concat([action.collection])
    }

  } else {
    return state
  }
}

你如何处理这一切取决于你。我试图在上面简单地说明这一点,但如果您愿意,可以使用thunk用于异步调用和switch语句或reducers的对象映射。

答案 1 :(得分:0)

要重述您的问题,您希望CRUD操作在完成后获取摘要,但您不希望操作必须知道摘要。

最好的方法(我能想到)就是在你的州里有一个stale标志(或者你想要的任何名字)。在reducer中,将陈旧标记标记为true,以获取从所有CRUD操作获得的每个接收操作的摘要。这样,操作不会耦合,但保证顺序更新。因此,摘要会听取所有行动。

下一步是检查摘要容器中的stale标志。假设您正在使用React,我认为componentWillUpdatehttps://facebook.github.io/react/docs/component-specs.html#updating-componentwillupdate)将是有用的。然后,您可以在那里触发fetchSummary操作。您也可以在初始渲染componentDidMounthttps://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount)上执行此操作。

答案 2 :(得分:0)

三年后,我以崭新的眼光和更多的经验来解决这个问题,我肯定会使用XState之类的方法将状态转换外部化。状态机将跟踪转换,而Redux将维护后备数据,向组件分发更新事件。