React集成CoinGeko API:刷新超3次加载失败及CORS报错问题
问题本质
核心是CoinGecko免费API请求超限(429错误),并非单纯CORS问题。刷新次数过多后,请求频率超过API限制,返回429响应时未携带Access-Control-Allow-Origin头,浏览器因此抛出CORS报错,最终导致应用陷入无限加载。
解决办法
1. 给请求加节流控制
限制请求频率,避免短时间内重复调用。可以用lodash.throttle或自定义节流逻辑:
import throttle from 'lodash.throttle'; // 限制每1.2秒发起一次请求(每分钟不超50次,留足余量避免触发限流) const fetchMarketData = throttle(async (page) => { try { const res = await fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&page=${page}&order=market_cap_desc&per_page=10&sparkline=false&price_change_percentage=1h%2C24h%2C7d`); if (!res.ok) { if (res.status === 429) { // 触发限流时,1分钟后重试并提示用户 setTimeout(() => fetchMarketData(page), 60000); alert('请求过于频繁,请稍后再试'); return; } throw new Error('数据加载失败'); } const data = await res.json(); // 这里更新你的应用状态 } catch (err) { console.error(err); } }, 1200);
2. 缓存已加载的页面数据
用状态或本地存储缓存已获取的页面数据,避免重复请求相同内容:
const [cachedPages, setCachedPages] = useState({}); const fetchMarketData = async (page) => { // 先读缓存,有数据直接用 if (cachedPages[page]) { setCoins(cachedPages[page]); return; } // 没有缓存再发起请求 const res = await fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&page=${page}&...`); const data = await res.json(); // 更新缓存 setCachedPages(prev => ({...prev, [page]: data})); // 更新应用状态 setCoins(data); };
3. 本地开发用代理转发
在package.json中添加代理配置,让请求通过本地服务器转发,减少前端直接请求被限流的概率:
{ "proxy": "https://api.coingecko.com" }
之后将请求URL改为相对路径:
await fetch(`/api/v3/coins/markets?vs_currency=usd&page=${page}&...`);
4. 优化429错误处理逻辑
检测到429状态码时,不要让应用无限加载,而是根据API返回的Retry-After头或默认值延迟重试,并给用户明确提示:
if (res.status === 429) { const retryAfter = res.headers.get('Retry-After'); const delay = (retryAfter ? parseInt(retryAfter) : 60) * 1000; setTimeout(() => fetchMarketData(page), delay); alert(`请求过于频繁,请${Math.floor(delay/1000)}秒后再试`); return; }
5. 升级付费API(可选)
如果应用需要更高的请求频率,可以考虑升级CoinGecko的付费API套餐,获取更高的调用限额。
内容的提问来源于stack exchange,提问作者imnotremi
相关产品推荐
相关产品推荐

