You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Flutter中利用Future.wait规避API请求超限问题

解决Flutter API调用触发DDOS防护限制的问题

原代码的问题

你当前的代码逻辑完全无法实现限流效果:Future.wait会一次性发起所有异步请求,根本做不到分批或控速;而且antiSpam变量在多个并发的异步回调里被同时修改,计数逻辑完全不可靠——多个异步函数会同时读写这个变量,导致判断条件彻底失效。

方案一:分批次请求(严格控制每秒20次)

把请求按每20个一组拆分,每组请求完成后等待1秒再发起下一组,完美匹配服务器的限流规则:

// 查询Token信息
final tokenMap = <String, Token>{};
final uniqueAddresses = tokenAddressList.toSet().toList();
const batchSize = 20;

for (int i = 0; i < uniqueAddresses.length; i += batchSize) {
  // 截取当前批次的地址(避免越界)
  final endIndex = min(i + batchSize, uniqueAddresses.length);
  final batch = uniqueAddresses.sublist(i, endIndex);
  
  // 发起当前批次的所有请求
  final batchResults = await Future.wait(
    batch.map((address) => sl.get<ApiService>().getToken([address])),
  );
  
  // 将结果存入map
  for (int j = 0; j < batch.length; j++) {
    tokenMap[batch[j]] = batchResults[j];
  }
  
  // 非最后一批次,等待1秒再继续
  if (endIndex < uniqueAddresses.length) {
    await Future.delayed(const Duration(seconds: 1));
  }
}

方案二:匀速控速(请求分布更平滑)

如果不想等整批完成再等待,可以让请求均匀分布在时间里,比如每50毫秒发起一个请求(刚好每秒20次),避免瞬间请求峰值:

// 查询Token信息
final tokenMap = <String, Token>{};
final uniqueAddresses = tokenAddressList.toSet().toList();
const requestInterval = Duration(milliseconds: 50); // 1秒20次,单次间隔50ms

for (int i = 0; i < uniqueAddresses.length; i++) {
  final address = uniqueAddresses[i];
  final token = await sl.get<ApiService>().getToken([address]);
  tokenMap[address] = token;
  
  // 非最后一个请求,等待间隔时间
  if (i != uniqueAddresses.length - 1) {
    await Future.delayed(requestInterval);
  }
}

额外优化建议

如果你的API支持批量查询(比如一次传入多个token地址),优先使用批量接口——这能直接把n次请求压缩成少数几次,从根本上规避限流问题,效率也会更高。

内容的提问来源于stack exchange,提问作者redDwarf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 21:30:41