为什么“await”在函数定义中需要“async”

jea*_*luc 4 javascript asynchronous promise dart

我目前正在学习 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;
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

这对我来说没有意义。如果一个函数正在等待一个异步函数完成,那么它不是被认为是阻塞的吗?为什么 JS 和 Dart 要求将其标记为异步?不会适得其反吧?

对我来说,如果调用函数在async调用任何在其定义中也包含它的函数时必须使用关键字,那将更有意义。在这种模式中,await将用于将异步函数转换为同步函数。

这种方式也可以避免重复的功能,因为现在,库似乎总是有func()andfuncSync()funcAsync()

Ste*_*ary 6

async/的基本语义await在 F#、VB、C#、Python、Dart、Hack 和 JavaScript 中是相同的。所以我认为这个问题有足够的其他语言的答案。但自从它重新开放以来......

如果一个函数正在等待一个异步函数完成,那么它不是被认为是阻塞的吗?

不。这样想:

  • “异步”的意思是“不阻塞调用线程”。
  • “同步”的意思是“阻塞调用线程”。

在异步方法/函数中,方法/函数可以在点处暂停await,但在暂停时不会阻塞调用线程。该函数串行运行(一次一个语句),但异步运行(不阻塞调用线程)。

对我来说,如果调用函数在调用任何在其定义中也包含它的函数时必须使用 async 关键字,那将更有意义。

这就是它已经工作的方式......await消耗承诺/未来/任务返回方法/函数,并将方法/函数async标记为能够使用await.

这种方式也可以避免重复的功能

这对于历史阻塞的命令式语言是不可能的。一个方法/函数要么阻塞调用线程直到它完成,要么不阻塞。它是同步的或异步的。

不过,有一些有趣的异步方法/函数替代方法:

Go 在历史上不是阻塞的;您可以将其视为一种语言,其中每个方法/函数都可能是异步的;在任何其他运行时执行此操作将是灾难性的,但是 Go 通过实现带有消息传递的严格 goroutine 系统来避免这些问题 - 不允许共享内存或线程。

另一个例子是纯函数式语言,其中 Future 只是另一个 monad,不需要对async/await关键字的特殊编译器支持。