前端接口失败重试怎么做才不会重复请求?
我在做用户登录功能,网络不稳定时想加个重试机制,但发现有时候会连续发好几次一样的请求,比如用户点一次登录,结果因为重试发了三次。我试过用 axios 的拦截器加 retry 逻辑,但没控制好并发。
现在用的是这种简单写法:
const request = (url, options) => {
let retries = 0;
const maxRetries = 3;
const attempt = () => {
return fetch(url, options).catch(err => {
if (retries < maxRetries) {
retries++;
return attempt();
}
throw err;
});
};
return attempt();
};
但这样每次调用 request() 都会新建一个 retry 实例,如果用户快速点击多次,就会同时跑好几个重试流程。有没有办法在组件层面或者请求层面对同一个请求做去重 + 重试?
简单有效的做法是用一个Map来管理pending状态的请求:
这样处理后,假设用户疯狂点击登录按钮,只有第一个请求会真正发出去,后面的请求会直接复用第一个请求的Promise,等第一个请求重试完或者成功失败后,所有点击都会拿到同样的结果。
如果想在组件层面更细粒度控制,可以在按钮点击时加个loading状态,用户点第一次就把按钮disabled掉,防止继续点击。这个配合上面的请求层去重,双重保险,基本就稳了。
还有个进阶思路是用AbortController,如果你想实现"取消之前的请求,只保留最后一次"这种行为,而不是"只发第一个请求"。看具体业务需求选用即可。