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

如何让async函数if/else两个分支的await等待逻辑都正常生效?

问题根源
  • 你当前定义的pendingRequestList、requestsList是函数内部局部变量,每次调用addResultToCache都会重新初始化,请求状态和缓存完全无法跨调用保留,状态判断本身就不生效
  • else分支没有等待正在执行的相同查询任务,直接走完逻辑返回,导致调用方的await提前结束,拿不到对应查询的结果
解决方案

你可以用Completer存储每个正在执行的查询任务,后续相同查询进入时直接等待已有Completer完成即可,调整后的代码如下:

// 状态变量移到函数外部,跨调用保留
List<RequestCacheStruct> requestsList = [];
// 用Map存储查询哈希对应的Completer,用于后续调用等待
Map<int, Completer<RequestCacheStruct>> pendingRequests = {};

Future<RequestCacheStruct> addResultToCache(String sqlQuery) async {
  final queryHash = sqlQuery.hashCode;

  // 已存在相同的正在执行的查询,直接返回对应Future等待完成
  if (pendingRequests.containsKey(queryHash)) {
    print("This query is already running, waiting for result...");
    return pendingRequests[queryHash]!.future;
  }

  // 首次执行该查询,新建Completer存入待执行Map
  final taskCompleter = Completer<RequestCacheStruct>();
  pendingRequests[queryHash] = taskCompleter;

  try {
    var queryResult = await connection.query(sqlQuery, timeoutInSeconds: 3600);
    var cacheObj = RequestCacheStruct(queryHash, DateTime.now(), queryResult);
    requestsList.add(cacheObj);
    print('Query was added to Cache');
    // 完成Completer,通知所有等待该查询的调用
    taskCompleter.complete(cacheObj);
    return cacheObj;
  } catch (err) {
    // 异常场景下也通知Completer,避免调用方永久挂起
    taskCompleter.completeError(err);
    rethrow;
  } finally {
    // 执行结束后从待执行Map移除
    pendingRequests.remove(queryHash);
  }
}
核心优化点
  • 持久化状态存储:将请求状态、缓存列表移到函数外部,保证跨调用状态可复用
  • 同查询任务复用:相同查询的并发调用都会等待同一个执行任务,不会重复发起数据库请求,也不会提前返回
  • 异常兼容:增加异常捕获逻辑,确保异常场景下所有等待的调用都能收到错误通知,不会出现Future永久未完成的问题
  • 结果可获取:函数直接返回查询结果结构体,调用方await后可以直接拿到结果,不需要再额外查缓存

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 20:15:03