获取数据时在 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
}
}
}
其他用户将使用此数据更新自己的状态,以便与服务器匹配。
我在这里非常努力地寻找正确的解决方案。目前,我正在使用 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
}
}
}
其他用户将使用此数据更新自己的状态,以便与服务器匹配。