首页 > 解决方案 > 使用带有 React 和 Redux 的 Socket.io 每秒处理一百次更新

问题描述

我有一个项目列表,这些项目是来自服务器的数据对象(大约 1000 个),我需要对其进行排序、过滤、放入 Redux 并连接到 React 表组件。我正在使用 socket.io 来侦听更新,这些更新发送这些单独的数据对象,然后需要将这些数据对象计算到表中。它们可以是更新、新的或删除现有的。

所以我的问题是管理这么多传入套接字数据事件的最佳方法是什么?我应该在将它们更新到我的 redux 状态之前限制它们吗?我不想不断更新我的 redux 状态,否则我的表格组件会重新渲染太多。

我的另一个选择是我可以请求所有“活动”数据的最新列表,而忽略更新事件。因此,也许每隔几秒钟就用所有最新数据更新整个表,而不是尝试每秒管理数百次更新。

标签: reactjsreduxsocket.ioreal-time-updates

解决方案


我会坚持使用 REST api 调用,但是在 redux 操作开始时伪造更新,除了可能在成功时向对象添加正确的 id 并仅在失败时恢复状态之外什么都不做。

在创建项目操作的情况下,您的减速器看起来像这样:

export default (state = {}, action) => {
  switch (action.type) {
    case ActionsTypes.CREATE_START:
      // make the temporary changes

    case ActionsTypes.CREATE_SUCCESS:
      // update the previous temporary id with a proper id

    case ActionsTypes.CREATE_FAILURE:
      // delete the temporary changes

    default:
      return state;
  }
};

你的行为是这样的:

const ActionLoading = item => ({
  type: ActionsTypes.CREATE_START,
  item,
});

const ActionSuccess = item => ({
  type: ActionsTypes.CREATE_SUCCESS,
  item ,
  createdItem,
});

const ActionFailure = item => ({
  type: ActionsTypes.CREATE_FAILURE,
  item,
});

export default todo => (dispatch) => {
  dispatch(ActionLoading(item)); // add the item to your state

  const updatedTodo = await TodoClient.create(todo)

  if (updatedTodo) {
    dispatch(ActionSuccess(item, createdItem)) // update the temp item with a real id
  } else {
    dispatch(ActionFailure(item)) // remove the temporary item 
  }
};

出于性能考虑,您必须为您正在管理的数据提供临时 ID,并让对地图中呈现的项目做出正确反应。我个人使用 lodash 的uniqueId

您还必须为更新和删除实现此行为,但基本相同:

  • 存储更改,更新您的对象而无需等待 api 并在失败时恢复更改。
  • 无需等待 api 即可删除您的对象,并在失败时将其弹出。

这将给人一种实时的感觉,因为所有内容都将立即更新,并且仅在出现非托管错误时才恢复。如果你足够信任你的后端,这就是要走的路。

编辑:刚刚看到您的更新,您可以坚持这种改变数据的方式(或成功更新状态的正常方式),但为了避免过多的复杂性和渲染时间,请确保使用keyBy存储数据。一旦您的项目被存储为一个由其 id 键入的对象数组,您将能够以 O(1) 的复杂性添加、删除和修改它们。此外,react 会明白它不需要重新渲染整个列表,而只需要重新渲染单个更新的项目。


推荐阅读