You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为带固定请求间隔的fetch轮询添加超时终止逻辑

解决方案

实现思路

通过标记位或者时间差判断是否达到15秒超时阈值,满足条件时直接终止递归调用即可,不需要改动原有异步逻辑结构。
下面提供两种实现方式:

方案1:时间差判断(实现简单,无需额外定时器)

每次进入重试分支时计算当前时间与轮询初始时间的差值,超过15s则直接触发弹窗终止递归。

完整代码:

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 pollStartTime = Date.now()
    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 {
        // 新增:判断是否超时
        const elapsed = Date.now() - pollStartTime
        if (elapsed >= 15000) {
          dispatch({
            type: constants.SHOW_DOWNLOAD_POPUP
          })
          return
        }
        await addDelay(5000)
        await subscribe(url)
      }
    }
    subscribe(url)
  } catch (error) {
    dispatch({
      type: constants.DOWNLOAD_REPORT_FAILURE,
      errorMessage: error.status
    })
  }
}

方案2:超时标记位(超时判定更精准,到15秒立刻终止)

提前设置15秒定时器修改终止标记位,每次进入重试分支前优先判断标记位状态。

完整代码:

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 {
    // 新增:超时标记与超时定时器
    let isPollTimeout = false
    const timeoutTimer = setTimeout(() => {
      isPollTimeout = true
    }, 15000)

    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') {
        // 成功后清除定时器,避免内存泄漏
        clearTimeout(timeoutTimer)
        window.location.href = resBody.url
        dispatch({
          type: constants.DOWNLOAD_REPORT_SUCCESS
        })
      } else {
        // 优先判断是否已经超时
        if (isPollTimeout) {
          dispatch({
            type: constants.SHOW_DOWNLOAD_POPUP
          })
          return
        }
        await addDelay(5000)
        await subscribe(url)
      }
    }
    subscribe(url)
  } catch (error) {
    dispatch({
      type: constants.DOWNLOAD_REPORT_FAILURE,
      errorMessage: error.status
    })
  }
}

内容的提问来源于stack exchange,提问作者sg055322

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 15:36:03