如何让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
相关产品推荐
相关产品推荐

