Abel
Abel

Reputation: 1614

SetTimeout infinite loop and run function once

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.

Upvotes: 3

Views: 3708

Answers (1)

dave
dave

Reputation: 64657

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"/>

Upvotes: 2

Related Questions