Flutter如何确保应用每秒仅发起一次API调用?
解决Flutter中API调用每秒限制问题
核心方案:全局请求节流+队列调度
单纯用delay或Timer无法解决问题——多个并发请求会被同时延迟,但仍可能挤在同一时间窗口触发。正确的做法是实现一个全局请求调度器,统一管控所有API调用,确保每秒仅执行一次请求,剩余请求排队等待下一个时间窗口。
实现步骤与代码示例
- 创建全局请求节流类,维护请求队列和最后请求时间:
class ApiThrottler { static final ApiThrottler _instance = ApiThrottler._internal(); factory ApiThrottler() => _instance; ApiThrottler._internal(); int _lastRequestTimestamp = 0; final Queue<Function> _requestQueue = Queue(); bool _isProcessing = false; // 调度API请求 Future<void> scheduleRequest(Function apiCall) async { _requestQueue.add(apiCall); if (!_isProcessing) { _processQueue(); } } Future<void> _processQueue() async { _isProcessing = true; while (_requestQueue.isNotEmpty) { final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; // 计算距离下一秒的等待时长 final waitTime = _lastRequestTimestamp == now ? 1000 - (DateTime.now().millisecondsSinceEpoch % 1000) : 0; if (waitTime > 0) { await Future.delayed(Duration(milliseconds: waitTime)); } // 执行队列首个请求 final apiCall = _requestQueue.removeFirst(); try { await apiCall(); } catch (e) { // 按需处理请求错误,比如重试或日志记录 print('API请求失败: $e'); } finally { _lastRequestTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; } } _isProcessing = false; } }
- 所有API调用替换为通过调度器执行:
// 原直接调用API的写法 // await http.get(Uri.parse('http://iot-device/api/action')); // 改为调度器管控 ApiThrottler().scheduleRequest(() async { await http.get(Uri.parse('http://iot-device/api/action')); });
关键逻辑说明
- 单例模式:确保整个应用只有一个调度器实例,统一管控所有请求。
- 请求队列:所有触发的API调用先进入队列,避免请求丢失。
- 时间窗口判断:每次处理队列时,检查当前时间是否与最后一次请求在同一秒,若是则等待到下一秒再执行。
- 异常隔离:单个请求失败不会导致整个队列停滞,保证后续请求正常处理。
额外优化方向
- 若需要优先处理紧急请求,可给队列添加优先级机制(比如使用优先级队列)。
- 根据服务器承受能力,可调整时间间隔阈值(比如允许500ms间隔而非严格1秒)。
- 添加队列长度监控,队列过长时可选择丢弃旧请求或给用户提示(依据业务需求)。
内容的提问来源于stack exchange,提问作者Harish Kandekar
相关产品推荐
相关产品推荐

