javascriptlong-pollingajax-polling

How to stop polling using timeout in fetch request while adding intervals


I am polling for my report adding 5 seconds interval between each request.

const addDelay = timeout => new Promise(resolve => setTimeout(resolve, timeout))

export const myReport = () => async (dispatch) => {
  dispatch({
    type: constants.DOWNLOAD_REPORT_REQUEST
  })

  let url = `/admin/dashboard/report.js?project_id=${projectId}&tool_id=${toolId}`

  try {
    const subscribe = async (uri) => {
      let response = await fetch(uri, {
        method: 'GET',
        headers: {
          'content-type': 'application/json',
          'x-api-token': `Bearer ${token}`
        }
      })
      const resBody = await response.json()
      if (resBody.status === 'success') {
        window.location.href = resBody.url
        dispatch({
          type: constants.DOWNLOAD_REPORT_SUCCESS
        })
      } else {
        await addDelay(5000)
        await subscribe(url)
        //   return;
        // setTimeout(() => {
        //   dispatch({
        //     type: constants.SHOW_DOWNLOAD_POPUP
        //   })
        //   return;
        // }, 15000);
      }
    }
    subscribe(url)
  } catch (error) {
    dispatch({
      type: constants.DOWNLOAD_REPORT_FAILURE,
      errorMessage: error.status
    })
  }
}

Now, here I want to stop the polling after 15 seconds and show a popup.

The issue is I cannot add setTimeout here because I am using async. Also it won't stop calling subscribe method again and again as it keeps getting in else part, return is not working.

I want to get out of else part, stop calling the function and show popup after 15 seconds over. How do I achieve this?


Solution

  • Your return statement can't possibly work because this function is recursive - it'll never get there if the fetch keeps failing. What about just adding an index to track how many times you've retried subscribe?

    const addDelay = (timeout) =>
      new Promise((resolve) => setTimeout(resolve, timeout));
    
    const failed = 0;
    
    export const myReport = () => async (dispatch) => {
      dispatch({
        type: constants.DOWNLOAD_REPORT_REQUEST,
      });
    
      let url = `/admin/dashboard/report.js?project_id=${projectId}&tool_id=${toolId}`;
    
      try {
        const subscribe = async (uri) => {
          let response = await fetch(uri, {
            method: 'GET',
            headers: {
              'content-type': 'application/json',
              'x-api-token': `Bearer ${token}`,
            },
          });
          const resBody = await response.json();
          if (resBody.status === 'success') {
            window.location.href = resBody.url;
            dispatch({ type: constants.DOWNLOAD_REPORT_SUCCESS });
          } else {
            if (failed >= 3) {
              // whatever you want to do on fail
            } else {
              failed += 1;
              await addDelay(5000);
              await subscribe(url);
            }
          }
        };
        subscribe(url);
      } catch (error) {
        dispatch({
          type: constants.DOWNLOAD_REPORT_FAILURE,
          errorMessage: error.status,
        });
      }
    };