Nginx限流后前端请求被拦,怎么处理429错误?

UP主~焕焕 阅读 19

我用Nginx做了限流配置,结果前端频繁调用接口时直接返回429了,页面卡住没法继续操作。有没有办法在JS里捕获这个状态并友好提示用户?

试过在axios拦截器里判断status === 429,但有时候请求压根没发出去,浏览器控制台只看到failed net::ERR_FAILED,根本拿不到响应状态码。

axios.interceptors.response.use(
  res => res,
  err => {
    if (err.response?.status === 429) {
      alert('请求太频繁,请稍后再试');
    }
    return Promise.reject(err);
  }
);
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
UP主~雯清
这问题我太熟悉了,Nginx限流直接在网关层干掉请求,前端确实拿不到429状态码,只看到 ERR_FAILED 是正常现象——因为压根没到后端,连HTTP响应都没生成。

先说结论:别指望前端能准确捕获429,得从两方面搞:

一是Nginx配置上,加个响应头,让前端能识别出来被限流了。比如在限流 zone 那块加个 add_header X-RateLimit-Retry-After $limit_req_status;,然后前端拦截器里检查这个自定义头:

axios.interceptors.response.use(
res => res,
err => {
if (err.response?.headers?.['x-ratelimit-retry-after'] === 'REJECTED') {
alert('请求太频繁,请稍后再试');
// 这里可以加个防抖重试逻辑
} else if (err.code === 'ECONNABORTED' || err.message.includes('timeout')) {
// 真·请求超时
} else if (!err.response && !err.code) {
// ERR_FAILED 大概率是Nginx挡了
alert('网络或服务端限流,请稍后再试');
}
return Promise.reject(err);
}
);


二是Nginx那块别光用 limit_req_status 429,建议改成 limit_req_status 420(虽然420不是标准码,但很多公司都这么用),或者干脆用 429 + 自定义header 双重信号,这样前端判断更可靠。

另外提醒一句,别在前端用 onerrortry catch 捞这种错误,浏览器层面根本拦不住,必须靠响应拦截器或者 axios 的 transformResponse 里做点手脚——但最稳妥的还是让Nginx返回个可识别的标识。

插件可以的话,用 nginx-ultimate-bad-bot-blocker 这类现成方案,它默认就加了 X-Request-Status 头,省得自己调。

最后说句掏心窝子的:429这事儿,前端能做的很有限,关键还是后端+网关配合给信号,别指望单靠前端兜底。
点赞 1
2026-02-27 13:10