如何处理eleventy-fetch的429错误?指数退避方案失效排查
关于eleventy-fetch 429错误指数退避重试失效的问题
我用eleventy-fetch发起请求,代码如下:
let response = await EleventyFetch(url, { duration: "1h", type: "json" });
但偶尔会触发错误:
Bad response for [url] (429): Too Many Requests (via Error)
我知道是请求太频繁,于是尝试实现指数退避重试,但方案没生效,错误还是会被抛出,重试代码如下:
let response; let attempts = 0; const maxAttempts = 5; while (attempts < maxAttempts) { try { response = await EleventyFetch(url, { duration: "1h", type: "json" }); break; // 请求成功就退出循环 } catch (err) { if (err.response && err.response.status === 429) { attempts++; const waitTime = Math.pow(2, attempts) * 1000; // 指数退避 console.warn(`Rate limit exceeded. Retrying in ${waitTime / 1000} seconds...`); await new Promise(resolve => setTimeout(resolve, waitTime)); } else { throw err; // 非429错误直接抛出 } } }
请问我的代码哪里出错了?
问题原因及修复方案
核心问题是eleventy-fetch默认会缓存所有请求结果,包括429错误的响应。你设置了duration: "1h",第一次触发429后,这个错误响应会被缓存1小时,后续的重试请求根本没发出去,直接读取了缓存里的错误,所以重试逻辑完全没生效。
修复步骤
- 在请求配置里添加
fetchOptions: { cache: "no-store" },强制跳过缓存,确保每次重试都是真实请求 - 可以优化指数退避的计算逻辑,避免第一次等待时间过长(比如从第0次失败开始计算等待时长)
修正后的代码:
let response; let attempts = 0; const maxAttempts = 5; while (attempts < maxAttempts) { try { response = await EleventyFetch(url, { duration: "1h", type: "json", // 强制跳过缓存,保证重试发起真实请求 fetchOptions: { cache: "no-store" } }); break; } catch (err) { if (err.response && err.response.status === 429) { attempts++; // 调整退避计算:第1次失败等1秒,第2次等2秒,以此类推 const waitTime = Math.pow(2, attempts - 1) * 1000; console.warn(`触发速率限制,${waitTime / 1000}秒后重试...`); await new Promise(resolve => setTimeout(resolve, waitTime)); } else { throw err; } } } // 处理所有重试都失败的情况 if (!response) { throw new Error(`已重试${maxAttempts}次,仍无法获取数据`); }
额外提示
如果目标API返回了Retry-After响应头,优先用这个头里的时间来等待,比固定指数退避更贴合API的限制规则。
内容的提问来源于stack exchange,提问作者Kyle Pollard
相关产品推荐
相关产品推荐

