Asynchronous dart中的异步编程
我与java有关如何执行线程/异步。我使用new Thread(target).start(),其中target是可运行的,这是在java中执行线程的一种方法。新的并发api有其他选择,但我们知道,在特定的调用中,新线程正在创建并传递任务 类似地,在Dart中如何实现异步? 我阅读了发送/接收端口、完成器/未来、生成函数。对我来说,唯一的函数是令人信服的语句,它将创建新线程。能否解释一下completer/future如何提供帮助。我知道它们接受回调,但javascript/dart中是否有一些隐式逻辑/规则,即回调总是在不同的线程中执行 下面是dart代码段/伪代码:Asynchronous dart中的异步编程,asynchronous,dart,Asynchronous,Dart,我与java有关如何执行线程/异步。我使用new Thread(target).start(),其中target是可运行的,这是在java中执行线程的一种方法。新的并发api有其他选择,但我们知道,在特定的调用中,新线程正在创建并传递任务 类似地,在Dart中如何实现异步? 我阅读了发送/接收端口、完成器/未来、生成函数。对我来说,唯一的函数是令人信服的语句,它将创建新线程。能否解释一下completer/future如何提供帮助。我知道它们接受回调,但javascript/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通信
- 定时功能-设置超时、设置间隔
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中的一个)