获取数据时在 componentDidMount 中使用 setInterval() 的一种更性能友好的方式

A more performance-friendly way to use setInterval() in componentDidMount when fetching data

我在这里非常努力地寻找正确的解决方案。目前,我正在使用 setInterval() 到 "poll" 我的服务器并检索对象数组。为了获取数据,我使用 axios。以下是相关函数:

  componentDidMount(){
    this.timer = setInterval(() => [this.getData(), this.getCustData()], 1000);
  }

  componentWillUnmount(){
    this.timer && clearInterval(this.timer);
    this.timer = false
  }

  getData = () => {
      axios.get('http://localhost:3001/api/v1/pickup_deliveries')
        .then((response) => {
            this.setState({
              apiData: response.data
            })
          })
        .catch((error)=>{console.log(error);});
  }

    getCustData = () => {
      axios.get('http://localhost:3001/api/v1/customers')
        .then((response) => {
            this.setState({
              custData: response.data
            })
          })
        .catch((error)=>{console.log(error);});
  }

该应用程序 运行 太慢了,而且经常会完全挂起服务器,导致整个应用程序无法使用。目前,它正在获取的数组有超过 1000 个对象,而且这个数字每天都在增长。如果我在不轮询服务器的情况下获取数据,我的应用程序的感觉是白天和黑夜。我不太确定答案是什么,但我知道我的做法是不正确的。

这只是用 setInterval() 嘲笑 "polling" 的本质吗?或者有没有办法只在 state 发生变化时获取数据?

如果我需要实现 SSE 或 WebSockets,我会经历这些麻烦,但我想看看是否有办法修复我当前的代码以获得更好的性能。

谢谢你听我说完。

在前端方面,我的建议是不要使用 setInterval,而是使用 setTimeout。

使用 setInterval,您的应用可能会发送另一个请求,即使之前请求的响应尚未返回(例如:花费了超过 1 秒)。最好只在收到上一个响应后 1 秒发送另一个请求。

componentDidMount() {
  getData();
}

getData = () => {
  fetch().then(() => {
    updateState();

    // schedule next request
    setTimeout(getData, 1000);
  });
}

您还应该尝试减少需要在前端完成的更新量,例如通过减少数据的数量。

但是,我认为最重要的是重新考虑应用程序的设计。轮询只会变得更大的巨大 JSON 不是可扩展的设计。这对服务器和客户端都不好。

如果您要做的是让客户端收到服务器端的任何更改通知,您应该查看 WebSocket。一个简单的想法是浏览器应该与服务器建立一个 WS 连接。在对服务器进行任何更新时,服务器不应向下发送整个数据,而应仅向客户端发送更新。然后客户端会更新自己的状态。

例如,假设 2 位用户打开同一页面,一位用户通过添加新产品进行更改。服务器将收到此请求并相应地更新数据库。它还会向所有打开的 WebSocket 连接广播一条消息(添加产品的连接除外),其中包含一个简单的对象,如下所示:

{
  "action": "INSERT",
  "payload": {
    "product": {
      "id": 123123,
      ... // other product data
    }
  }
}

其他用户将使用此数据更新自己的状态,以便与服务器匹配。