我正在为一家德国公司判断Dart,方法是将各种Java程序移植到Dart,并对结果进行比较和分析.在浏览器中,Dart可以轻松获胜.对于服务器软件来说,性能似乎是一个严重的问题(见this question of me),但这基本上被化解了.

现在我正在移植一些"简单的"命令行工具,我完全没有想到会有任何严重的问题,但至少有一个问题.有些工具确实会发出HTTP请求来收集某些数据,并且独立的DART虚拟机仅以异步方式支持它们.纵观我所能发现的一切,似乎不可能在基本上同步的软件中使用任何异步调用.

我知道我可以将可用的同步软件重组为异步软件.但这会将设计良好的软件转变为可读性较差、更难调试和维护的软件.对于某些软件来说,这是没有意义的. 我的问题是:有没有一种方法(我忽略了)将异步调用嵌入到同步调用的方法中?

我想,提供一个只能从主线程内部使用的系统调用并不困难,它只需将执行转移到排队的整个异步函数调用列表中(而不必先结束主线程),一旦最后一个函数被执行,就返回并继续主线程.

可能看起来像这样的东西:

var synchFunction() {
  var result;
  asyncFunction().then(() { result = ...; });

  resync(); // the system call to move to and wait out all async execution

  return result;
}

拥有这样的方法也可以简化libAPI.大多数"同步"呼叫可以被移除,因为重新同步呼叫可以完成这项工作.这似乎是一个如此合乎逻辑的 idea ,以至于我仍然认为它以某种方式存在,而我错过了它.或者,有什么严肃的原因导致这种做法行不通吗?


After thinking about the received answer from lm (see below) for two days I still do not understand why the encapsulation of an asynchronous Dart call into a synchronous one should not be possible. It is done in the "normal" synchronous programing world all the time. Usually you can wait for a resynchronization by either getting a "Done" from the asynchronous routine or if something fails continue after a timeout.

考虑到这一点,我的第一个建议可以这样加强:

var synchFunction() {
  var result;
  asyncFunction()
    .then(() { result = ...; })
    .whenComplete(() { continueResync() }); // the "Done" message

  resync(timeout); // waiting with a timeout as maximum limit

  // Either we arrive here with the [result] filled in or a with a [TimeoutException].
  return result;
}

resync()执行的操作与结束Isolate的main方法后通常发生的相同,它开始执行排队的异步函数(或等待事件使其可执行).一旦它遇到continueResync()调用,就设置停止该异步执行的标志,并且resync()返回到主线程.如果在给定的timeout周期内没有遇到continueResync()调用,则它也中止异步执行,并以TimeoutException离开resync().

对于一些受益于直接同步编程的软件组(不是客户端软件,也不是服务器软件),这样的功能将为必须处理仅异步库的编程人员解决许多问题.

我相信我也为下面lm篇论证中的主要论点找到了解决方案.因此,关于我提出的"强化"解决方案,我的问题仍然存在:Is there anything which really makes it impossible to implement that in Dart?

推荐答案

唯一可以将异步方法包装在同步方法中的时候是不需要获取返回值的时候.

例如,如果要禁用"保存"按钮,将结果异步保存到服务器,并在作业(job)完成后重新启用"保存"按钮,则可以这样编写:

Future<bool> save() async {
  // save changes async here
  return true;
}

void saveClicked() {
  saveButton.enabled = false;
  save()
    .then((success) => window.alert(success ? 'Saved' : 'Failed'))
    .catchError((e) => window.alert(e))
    .whenComplete(() { saveButton.enabled = true; });
}

请注意,saveClicked方法是完全同步的,但异步执行save方法.

请注意,如果设置为saveClicked异步,则不仅必须使用异步模式调用它,而且整个方法体都将异步运行,因此在函数返回时不会禁用保存按钮.

为了完整起见,saveClicked的异步版本如下所示:

Future<Null> saveClicked() async {
  saveButton.enabled = false;
  try {
    bool success = await save();
    window.alert(success ? 'Saved' : 'Failed');
  }
  catch (e) {
    window.alert(e);
  }
  finally {
    saveButton.enabled = true;
  }
}

Dart相关问答推荐

dart - 通过异步等待避免递归 Stackoverflow

构造函数:将预处理的参数存储在传递给最终字段的辅助变量中

flutter.io (dart) - 将填充设置为设备宽度的百分比?

在构建函数之外使用 BuildContext

如何使用 Android aar 文件构建 Flutter 项目?

try 部署到 Google AppEngine 时出现 Dev_appserver.py 错误

Flutter更新导航栏

Dart/Flutter判断值是否为整数

不要将 PageView 居中 - Flutter

如何修复 Flutter 中的Checking Dart SDK version... << was unexpected at this time错误?

我如何在屏幕上弹出特定的Flutter

Expansion Panel底部溢出

无法使用 Flutter 调用 Localhost,将随机端口分配给 HTTP GET 调用

从 HttpClientResponse 检索响应正文

Dart 语法高亮不是高亮 dart 代码

在 Dart 中发送 SMTP 邮箱

如何在抽象类中声明工厂构造函数?

从dart语言列表中过滤空值的最佳方法是什么

使用 VSCode 创建和运行 Dart 控制台应用程序?

Dart 是否支持枚举?