我目前正在学习Dart,但这也适用于现在JavaScript世界中正在发生的事情,似乎C#也使用相同的模式。
在Dart中,使用await
的任何函数本身都必须通过async
标记为异步,如下所示:
import "dart:html";
main() async {
var context = querySelector("canvas").context2D;
var running = true;
while (running) {
var time = await window.animationFrame;
...
}
}
这对我没有意义。如果某个函数正在等待异步函数完成,那么它是否会被视为阻塞?为什么JS和Dart要求它被标记为异步?这不是相反的吗?
对我来说,如果调用函数必须使用async
关键字,如果它调用任何在其定义中也包含它的函数,那将更有意义。在此模式中,await
将用于将异步函数转换为同步函数。
这种方式也可以避免重复的功能,因为现在,库似乎总是func()
和funcSync()
或funcAsync()
。
答案 0 :(得分:4)
async
/ await
的基本语义在F#,VB,C#,Python,Dart,Hack和JavaScript中是相同的。所以我认为这个问题有其他语言的充分答案。但是因为它已经重新开放......
如果某个函数正在等待异步函数完成,那么它是否会被视为阻塞?
没有。以这种方式思考:
在异步方法/函数中,方法/函数可以在await
点暂停,但它在暂停时不会阻塞调用线程。该函数以串行(一次一个语句)运行,但异步(不阻塞调用线程)。
对我来说,如果调用函数必须使用async关键字,如果它调用在其定义中也包含它的任何函数,那将更有意义。
它是如何运作的...... await
使用promise / future / task-returns方法/函数,而async
标记一个方法/函数能够使用{{1} }}
这种方式也可以避免重复的功能
历史阻碍命令式语言无法做到这一点。方法/函数要么阻塞调用线程直到它完成,要么阻止它。它是同步的或异步的。
但是,异步方法/函数有一些有趣的替代方法:
Go不是历史上的阻碍;您可以将其视为一种语言,其中每个方法/函数都可能异步;在任何其他运行时执行此操作将是灾难性的,但Go通过实现具有消息传递的严格goroutine系统来避免这些问题 - 不允许共享内存或线程。
另一个例子是纯函数式语言,其中Future只是另一个monad,并且不需要特殊的编译器支持await
/ async
个关键字。
答案 1 :(得分:0)
在Dart中async
表示需要重写包含await
的代码。
async
/ await
只是Future.then()
基本API的语法糖,在编译和执行代码之前,代码会重写为此基于规范Future
的形式。
因此await
不会阻止代码。
对于生成器,还有其他受支持的标记,如*sync
和*async
。
另见 - Dart async/await internals - https://www.dartlang.org/articles/language/await-async
答案 2 :(得分:-3)
我不确定您的问题与C#有什么关系,但await
是C#中最不幸的关键字选择。如果您将其视为await
或resume after
,则yield then resume after
更易理解。当执行遇到await
时,它会挂起当前函数,返回其调用者。一旦等待的Task
完成,当调用者需要结果{来自await
表达式await
时,执行将在{{1}}之后恢复。
答案 3 :(得分:-3)
这是对“引擎盖下”发生的事情的一个基本误解,我假设javascript async / await实现镜像(至少在概念上)是.NET世界的镜像(起源于F#)。 / p>
本质:
在这个扩展的上下文中,关键字是有意义的:
只需考虑async并等待不可见的回调,async指示何时可以监听某些内容,并且await实际上是在监听。