前端接口失败重试怎么做才不会重复请求?

光浩 Dev 阅读 2

我在用 Vue 做一个数据上报的功能,网络不稳定时想自动重试,但发现有时候会触发多次重复请求,比如用户快速切换页面又回来,或者组件销毁后还在 retry。我试过用 setTimeout 递归,但控制不好取消逻辑。

下面是我现在的简化代码,求问怎么改才能安全地重试,又不会在组件卸载后还发请求?

<script>
export default {
  methods: {
    async fetchData(retryCount = 0) {
      try {
        await api.getData();
      } catch (err) {
        if (retryCount  this.fetchData(retryCount + 1), 1000);
        }
      }
    }
  },
  mounted() {
    this.fetchData();
  }
}
</script>
我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
Air-克培
这问题太常见了,搞不好就会变成请求地狱。通用的做法是用一个控制器来管理重试,同时处理组件卸载时的清理。

给你个靠谱的解决方案:
1. 用AbortController取消请求
2. 在组件销毁时清理定时器和取消请求
3. 用flag标记组件是否已卸载

改后的代码长这样:

export default {
data() {
return {
isMounted: false,
retryTimer: null,
abortController: null
}
},
methods: {
async fetchData(retryCount = 0) {
if (!this.isMounted) return

this.abortController?.abort()
this.abortController = new AbortController()

try {
await api.getData({
signal: this.abortController.signal
})
} catch (err) {
if (retryCount < 3 && err.name !== 'AbortError') {
this.retryTimer = setTimeout(() => {
this.fetchData(retryCount + 1)
}, 1000)
}
}
}
},
mounted() {
this.isMounted = true
this.fetchData()
},
beforeUnmount() {
this.isMounted = false
this.abortController?.abort()
clearTimeout(this.retryTimer)
}
}


几个关键点:
1. isMounted控制组件状态,避免卸载后还执行
2. AbortController能真正中断fetch请求
3. beforeUnmount里做清理工作

实际项目中可能还要加个防抖,防止用户疯狂操作。不过这个基础版已经能解决你的问题了。
点赞
2026-03-08 14:31