SetTimeout infinite loop and run function once

Viewed 1581

I need to reduce the amount of network calls from setInterval function. Every 3 seconds, API is called. The first API sometimes takes longer time to receive a response from the server.

Code

useEffect(() => {
 const id = setInterval(async () => {
  console.log('hello')
  await callAPI()
  console.log('bye')
 }, 3000);
 return () => {
  clearInterval(id);
 };
})

Problem

The setInterval function calls the callAPI method every 3 seconds while the first call API method still running waiting for server response which results in many API calls which are spamming server.

Expected

SetInterval function should wait for the first method called's response, before running method again every 3 seconds.

1 Answers

I would just use a setTimeout that calls itself:

useEffect(async () => {
 let id;
 const api = async () => {
    console.log('hello')
    await callAPI()
    console.log('bye')
    id = setTimeout(api, 3000);
 });
 await api();
 return () => {
  clearTimeout(id);
 };
})

For example:

const api = () => {
    console.log('hi');
    setTimeout(api, 1000);
    console.log('bye');
}

api();

    const Example = props => {
      const [countdown, setCountdown] = React.useState(100);
      React.useEffect(() => {
          const timeout = setTimeout(() => {
              setCountdown(countdown - 1);
          }, 1000);
          return () => {
              clearTimeout(timeout);
          }
      }, [countdown]);
      
      return (<div>{countdown}</div>)
    }


    // Render it
    ReactDOM.render(
      <Example />,
      document.getElementById("react")
    );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>

    <div id="react"/>

Related