如何使异步 Dart 调用同步? [英] How to make an asynchronous Dart call synchronous?

查看:23
本文介绍了如何使异步 Dart 调用同步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过将各种 Java 程序移植到 Dart 并比较和分析结果来为一家德国公司评估 Dart.在浏览器中,Dart 胜出.对于服务器软件性能似乎是一个严重的问题(参见 我的这个问题) 但大部分都被解除了.

I'm on the way to evaluate Dart for a German company by porting various Java programs to Dart and compare and analyze the results. In the browser Dart wins hands down. For server software performance seemed to be a serious isssue (see this question of me) but that got mostly defused.

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

Now I'm in the area of porting some "simple" command-line tools where I did not expect any serious problems at all but there is at least one. Some of the tools do make HTTP requests to collect some data and the stand-alone Dart virtual machine only supports them in an asynchronous fashion. Looking through all I could find it does not seem to be possible to use any asynchronous call in a mostly synchronous software.

我知道我可以将可用的同步软件重组为异步软件.但这会将精心设计的软件变成可读性较差且更难调试和维护的软件.对于某些软件而言,这毫无意义.我的问题:有没有(我忽略的)方法可以将异步调用嵌入到同步调用的方法中?

I understand that I could restructure the available synchronous software into an asynchronous one. But this would transform a well-designed piece of software into something less readable and more difficult to debug and maintain. For some software pieces this just does not make sense. My question: Is there an (overlooked by me) way to embed an asynchronous call into a synchronously called method?

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

I imagine that it would not be to difficult to provide a system call, usable only from within the main thread, which just transfers the execution to the whole list of queued asynchronous function calls (without having to end the main thread first) and as soon as the last one got executed returns and continues the main thread.

看起来像这样的东西:

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

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

  return result;
}

拥有这样的方法也会简化 lib API.大多数同步"调用可以被删除,因为重新同步调用可以完成这项工作.这似乎是一个如此合乎逻辑的想法,以至于我仍然认为它以某种方式存在并且我已经错过了.或者是否有一个严重的原因导致它不起作用?<小时>在思考了两天从 lm(见下文)收到的答案后,我仍然不明白为什么将异步 Dart 调用封装为同步调用是不可能的.它一直在正常"同步编程世界中完成.通常,您可以通过从异步例程中获取完成"或超时后继续执行某些操作来等待重新同步.

Having such a method would simplify the lib APIs as well. Most "sync" calls could be removed because the re-synchronisation call would do the job. It seems to be such a logical idea that I still think it somehow exists and I have missed it. Or is there a serious reason why that would not work?


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.

考虑到这一点,我的第一个提案可以这样增强:

With that in mind my first proposal could be enhanced like that:

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() 执行的操作与结束隔离的 main 方法后通常会发生的情况相同,它开始执行排队的异步函数(或等待事件使它们可执行).一旦遇到 continueResync() 调用,就会设置一个标志,停止异步执行并且 resync() 返回到主线程.如果在给定的 timeout 时间段内没有遇到 continueResync() 调用,它也会中止异步执行并给 resync() 留下一个 超时异常.

The resync() does the same that would normally happen after ending the main method of an isolate, it starts executing the queued asynchronous functions (or waits for events to make them executable). As soon as it encounters a continueResync() call a flag is set which stops this asynchronous execution and resync() returns to the main thread. If no continueResync() call is encountered during the given timeout period it too aborts the asynchronous execution and leaves resync() with a TimeoutException.

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

For some groups of software which benefit from straight synchronous programing (not the client software and not the server software) such a feature would solve lots of problems for the programer who has to deal with asynchrounous-only libraries.

我相信我在下面lm的论证中也找到了主要论证的解决方案.因此,对于我提出的这个增强型"解决方案,我的问题仍然存在:有什么事情真的无法在 Dart 中实现吗?

I believe that I have also found a solution for the main argument in lm's argumentation below. Therefore my question still stands with respect to this "enhanced" solution which I proposed: Is there anything which really makes it impossible to implement that in Dart?

推荐答案

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

The only time that you can wrap an async method in a synchronous one is when you don't need to get a return value.

例如,如果您想禁用保存按钮,将结果异步保存到服务器并在工作完成后重新启用保存按钮,您可以这样编写:

For example if you want to disable the save button, save results to the server asynchronously and re-enable the save button when the job is done you can write it like this:

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 方法.

Note that the saveClicked method is fully synchronous, but executes the save method asynchronously.

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

Note that if you make saveClicked async, not only do you have to call it using the async pattern, but the entire method body will run asynchronously so the save button will not be disabled when the function returns.

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

For completeness the async version of saveClicked looks like this:

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 调用同步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆