【问题标题】:Dart: Exit of a async method without any traceDart:异步方法的退出没有任何痕迹
【发布时间】:2020-05-10 09:44:28
【问题描述】:

将达到以下方法。但是这 3 个日志语句都不会被触发。

void readAndExecute(String sql, 列表参数, CallbackOnSingleRow onSingleRow) 异步 { _lastResults = null; await _dbConnection.query(sql, parameters).then((Results result) { _logger.log('发现了什么', LEVEL_FINE); for (var row in result) { _lastResults ??= 结果; onSingleRow(行); } }).catchError((错误) { _logger.error('读取失败:$error\n$sql'); throw DbException('readAndExecute()', sql, parameters, error.toString()); }); _logger.log('readAndExecute() 已到达', LEVEL_FINE); }
  • _dbConnection 是一个有效的 MySqlConnection 实例(成功登录)
  • sql 是有效的 SQL 语句(使用 DB 工具测试):
  • sql: select * from users where user_id > ?;
  • 参数:[0]
  • 数据包mysql1的日志被激活,输出为:
FINE:2020-05-10 11:33:40.060170:启动“PrepareHandler”的处理程序实例 FINE:2020-05-10 11:33:40.060748:sendBuffer 标头 FINE:2020-05-10 11:33:40.060938:发送标头,数据包 0 罚款:2020-05-10 11:33:40.061021:writeBuffer 长度 = 4 罚款:2020 年 5 月 10 日 11:33:40.061091:_writeBuffer 偏移量 = 0 FINE:2020-05-10 11:33:40.061278:写了 4 个字节 罚款:2020-05-10 11:33:40.061438: 38 00 00 00 8···

恐怕我对“async-await”的概念有些理解。

回答1后代码改为:

尝试 { _lastResults = 等待 _dbConnection.query(sql, 参数); _logger.log('达到结果', LEVEL_FINE); for(_lastResults 中的 var 行){ onSingleRow(行); } } 捕捉(除外){ _logger.error('readAndExecute(): $exc\n$sql'); }

但问题仍然存在:2 个日志将无法到达。

【问题讨论】:

  • 您可以使用await 并将返回值存储为变量,或者使用.then() 并使用您在then 中获得的值执行一个函数。我看不出你同时给他们两个打电话的意义
  • 你说得对,那是我的误解。 await 变体符合我的要求。
  • 我改了代码,问题依旧。
  • await 行上方放置一个记录器,看看它是否打印
  • await 上方的日志语句可以正常工作。

标签: dart async-await


【解决方案1】:

在这里,我简化了您提供的两个版本的代码:

Future readAndExecute() async {
  print(1);
  await Future.delayed(Duration(seconds: 1)).then((i) {
    print(2);
  }).catchError((error) {
    print(3);
    throw "thrown";
  });
  print(4);
}
// prints:
// 1
// 2
// 4

Future secondTry() async {
  try {
    await Future.delayed(Duration(seconds: 1));
    print(1);
  } catch (exc) {
    print(2);
  }
}

// prints:
// 1

谈到第二个,你应该看到result reached(在我的例子中是1),如果_dbConnection.query(sql, parameters)确实完成了。

我真的会确保函数被实际调用。在函数中的任何其他内容之前放置一个日志,看看您是否在日志中看到它。所以:

    _logger.log('CALLED INDEED', LEVEL_FINE);
    try {
      _lastResults = await _dbConnection.query(sql, parameters);
      _logger.log('result reached', LEVEL_FINE);
      for (var row in _lastResults) {
        onSingleRow(row);
      }
    } catch (exc) {
      _logger.error('readAndExecute(): $exc\n$sql');
    }

Future secondTry() async {
  print(0);
  try {
    await Future.delayed(Duration(seconds: 1));
    print(1);
  } catch (exc) {
    print(2);
  }
}

【讨论】:

  • @Gzihan:起初我想:代码和我的问题有什么关系?但不起作用的抽象表明问题更为根本。真正的问题是调用堆栈中包含一个没有“等待”的调用。谢谢。
猜你喜欢
  • 2021-03-18
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
  • 2019-05-19
  • 1970-01-01
  • 2016-02-22
相关资源
最近更新 更多