如何在添加间隔的同时在获取请求中使用超时来停止轮询

问题描述 投票:0回答:3

我正在轮询我的报告,并在每个请求之间添加 5 秒的间隔。

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

现在,我想在 15 秒后停止轮询并显示一个弹出窗口。

问题是我无法在此处添加 setTimeout,因为我正在使用

async
。而且它不会停止一次又一次地调用
subscribe
方法,因为它不断进入其他部分,
return
不起作用。

我想退出 else 部分,停止调用该函数并在 15 秒后显示弹出窗口。我如何实现这一目标?

javascript long-polling ajax-polling
3个回答
0
投票

你的 return 语句不可能工作,因为这个函数是 recursive - 如果获取一直失败,它永远不会到达那里。只需添加一个索引来跟踪您重试订阅的次数怎么样?

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


0
投票

您可以跟踪自轮询开始以来已经过去的时间量,并在其达到零时退出。

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}`

  let remainingPollingTime = 15000 // <--------
  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(remainingPollingTime <= 0) { // <--------
          dispatch({
            type: constants.SHOW_DOWNLOAD_POPUP
          })
          return
        }

        remainingPollingTime -= 5000 // <--------
        await addDelay(5000)
        await subscribe(url) 
      }
    }
    subscribe(url)
  } catch (error) {
    dispatch({
      type: constants.DOWNLOAD_REPORT_FAILURE,
      errorMessage: error.status
    })
  }
}

-1
投票

我编写了一个小型 JavaScript 库,您可能会发现对这种情况有用。它可以让您很好地控制间隔,并跟踪内置的轮询持续时间👍

https://github.com/IlyaGershman/easy-poll

© www.soinside.com 2019 - 2024. All rights reserved.