AttemptedMastery
AttemptedMastery

Reputation: 768

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

i am struggling pretty hard here to find the right solution. Currently, I am using setInterval() to "poll" my server and retrieve an array of objects. To fetch the data, I am using axios. Here are the pertinent functions:

  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);});
  }

The application is running so slow and often times, it will completely hang the server which makes the whole application unusable. Currently the array it's fetching has over 1000+ objects and that number is growing daily. If I fetch the data without polling the server, the feel of my application is night and day. I am not quite sure what the answer is but I do know what I am doing is NOT the right way.

Is this just the nature of mocking "polling" with setInterval() and it is what it is? Or is there a way to fetch data only when state has changed?

If I need to implement SSE or WebSockets, I will go through the hassle but I wanted to see if there was a way to fix my current code for better performance.

Thanks for hearing me out.

Upvotes: 1

Views: 1048

Answers (1)

Jackyef
Jackyef

Reputation: 5012

On the frontend side, my advice would be to not use setInterval, but use setTimeout instead.

Using setInterval, your app might send another request even if the response for previous request hasn't come back yet (e. g.: it took more than 1 second). Preferably, you should only send another request 1 second after the previous response is received.

componentDidMount() {
  getData();
}

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

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

You should also try to reduce the amount of updates that need to be done on the frontend, for example by reducing the number of the data.

But nevertheless, I think the most important is to rethink the design of your application. Polling huge JSON that is going to only grow bigger is not a scalable design. It's bad for both the server and the client.

If what you are trying to do is to have the client be notified of any changes in the server side, you should look into WebSocket. A simple idea is that the browser should establish a WS connection to the server. Upon any updates to the server, instead of sending down the whole data, the server should only send down the updates to the client. The client would then update its own state.

For example, let's say 2 users are opening the same page, and one user make changes by adding a new Product. Server will receive this request and update the database accordingly. It will also broadcast a message to all open WebSocket connections (except for the one connection that added the Product), containing a simple object like this:

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

The other user will use this data to update its own state so it matches the server.

Upvotes: 1

Related Questions