Asynchronous dart中的异步编程

Asynchronous dart中的异步编程,asynchronous,dart,Asynchronous,Dart,我与java有关如何执行线程/异步。我使用new Thread(target).start(),其中target是可运行的,这是在java中执行线程的一种方法。新的并发api有其他选择,但我们知道,在特定的调用中,新线程正在创建并传递任务 类似地,在Dart中如何实现异步? 我阅读了发送/接收端口、完成器/未来、生成函数。对我来说,唯一的函数是令人信服的语句,它将创建新线程。能否解释一下completer/future如何提供帮助。我知道它们接受回调,但javascript/dart中是否有一些

我与java有关如何执行线程/异步。我使用new Thread(target).start(),其中target是可运行的,这是在java中执行线程的一种方法。新的并发api有其他选择,但我们知道,在特定的调用中,新线程正在创建并传递任务

类似地,在Dart中如何实现异步? 我阅读了发送/接收端口、完成器/未来、生成函数。对我来说,唯一的函数是令人信服的语句,它将创建新线程。能否解释一下completer/future如何提供帮助。我知道它们接受回调,但javascript/dart中是否有一些隐式逻辑/规则,即回调总是在不同的线程中执行

下面是dart代码段/伪代码:

void callback(){
打印(“调用回调”);
}
costlyQuery(sql,void f()){
executeSql(sql);
f();
}
costlyQuery(“选择*从双”,回调);

我希望我的costlyQuery签名将函数作为第二个参数是正确的。所以现在我不认为
executeSql(sql)
之后的
f()
是异步的。可能是以上面的例子添加completer/future,如果这可以使async帮助我理解。

tl;dr:回调不会阻止的隐式规则不存在

Javascript事件队列 在Javascript中,没有线程(除了WebWorkers,但这是不同的)。这意味着,如果代码的任何部分被阻塞,整个应用程序将被阻塞。回调没有什么神奇之处,它们只是函数:

函数长循环(cb){
var i=1000000;
而(我--),;
cb();
}
函数回调(){
log(“你好世界”);
}
函数fun(){
长循环(回调);
log(“打印Hello World后调用”);
}
要实现异步,回调必须放在事件队列上,这只能通过一些API调用发生:

  • 用户启动的事件处理程序-单击、键盘、鼠标
  • API事件处理程序-XmlHTTPRequest回调,WebWorker通信
  • 定时功能-设置超时、设置间隔
当事件被触发时,回调将被放置在事件队列上,以便在所有其他回调都已完成执行时执行。这意味着您的代码不会同时执行两行

期货 我想你至少偶然发现了。如果不是,这是一本很好的读物,而且是直接从马嘴里读出来的

在Javascript中,您必须做一些工作来理解异步代码。甚至还有一个Javascript库,用于处理常见的事情,例如异步循环和序列(完全公开,我个人与该库的作者合作过)

未来的概念是创造未来的职能部门做出的承诺,即未来将在未来的某个时刻完成。如果您要进行一些异步调用,请创建一个未来,返回它,并在异步调用完成时履行承诺。从博客帖子:

Future costlyQuery(){
var completer=new completer();
database.query(“从巨表中选择*”,(结果){
//完成时
完成者。完成(结果);
});
//这基本上是立即返回的,
//在查询完成之前
返回completer.future;
}
如果database.query是一个阻塞调用,则未来将立即完成。本例假设
database.query
是一个非阻塞调用(异步),因此将来将在该函数退出后执行
completer.complete
将调用传递给
completer.then()的任何函数,并指定参数

您的示例已修改为惯用和异步:

void callback(){
打印(“调用回调”);
}
costlyQuery(sql){
var completer=new completer();
executeSql(sql,()=>completer.complete());
返回completer.future;
}
costlyQuery(“从双精度中选择*)。然后(回调);
这是异步的,并且正确地使用了未来。您可以像以前那样将自己的回调函数传递到
costlyQuery
,并在调用
executeSql
的回调中调用该函数,以实现同样的效果,但这是Javascript的方法,而不是Dart方法

隔离 隔离与Java的线程类似,只是隔离是一个并发模型,线程是一个并行模型(有关并发与并行的更多信息,请参阅)

Dart的特殊之处在于,该规范并不要求所有内容都在一个线程中运行。它只要求不同的执行上下文不能访问相同的数据。每个隔离都有自己的内存,只能通过发送/接收端口与其他隔离进行通信(如发送数据)

如果您熟悉,这些端口的工作方式与Go中的通道类似

隔离是独立于其他代码运行的隔离执行上下文。在Javascript术语中,这意味着它有自己的事件队列。有关更完整的分离物介绍,请参阅

假设executeSql是一个阻塞函数。如果我们不想等待它完成,我们可以将其加载到隔离中:

void callback(){
打印(“调用回调”);
}
void costlyQuery(){
port.receive((sql,reply){
executeSql(sql);
答复.发送();
});
}
main(){
var sendPort=spawn函数(costlyQuery);
//.call提供了双向沟通所需的所有魔法
调用(“从双通道中选择*)。然后(回调);
打印(“在executeSql完成之前调用”);
}

这段代码创建一个隔离,向它发送数据,然后在完成时注册一个回调。即使
executeSql
阻塞,
main()
也不一定会阻塞。

谢谢您的解释。不过我有一个疑问。在使database.query成为非bloc时使用了哪个api调用(应该是您列出的UI、api、setInterval/setTimeout中的一个)