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

问题描述 投票:1回答:1

我在这里努力寻找正确的解决方案。当前,我正在使用setInterval()“轮询”服务器并检索对象数组。要获取数据,我正在使用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()模拟“轮询”的本质,它是什么吗?还是只有在state更改后才可以获取数据?

如果我需要实现SSE或WebSocket,我会遇到麻烦,但是我想看看是否有一种方法可以修复当前代码以提高性能。

感谢您听到我的声音。

reactjs fetch settimeout setinterval polling
1个回答
1
投票

在前端,我的建议是不要使用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
    }
  }
}

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

© www.soinside.com 2019 - 2024. All rights reserved.