Javascript 为什么';等待&x27;需要';异步';在函数定义中

Javascript 为什么';等待&x27;需要';异步';在函数定义中,javascript,asynchronous,promise,dart,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 wi

我目前正在学习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()
我不确定你的问题与C有什么关系,但是
wait
是C中最不幸的关键字选择<如果将代码>等待理解为
之后继续甚至
之后继续,则更容易理解。当执行遇到
wait
时,它将暂停当前函数,并返回其调用者。一旦等待的
任务
完成,调用方需要结果时(从其自身的
等待
表达式)在
等待
之后继续执行。

这是对“幕后”情况的根本误解,我假设javascript异步/等待实现是镜像的(至少在概念上)是.NET世界(起源于F#)

基本上:

  • 排序的“工作单元”标记(在C#中是JS中的任务,在JS中是承诺)表示任务的完成,并带有返回值的选项
  • “asynchronous”方法标记为async,以向编译器/解释器/运行时指示该方法将返回所述令牌,并且可能会消耗一些令牌
  • 运行这一切的thingamajig(在C#的情况下)将偷偷地重写代码,以基本上完成以下操作:

  • 启动异步方法
  • 标准正常代码
  • 遭遇“令牌”提供方法
  • 叫它,拿令牌
  • 设置代码稍后可以跳回的位置
  • 令牌是否已完成?如果已完成,请继续,如果未完成,请设置一个回调,以便运行时在完成时返回到此位置

  • 在这个扩展的上下文中,关键字是有意义的:

  • 异步(异步)-执行某些任务的方法,这些任务可能需要不确定的时间,可以等待
  • wait-表示您不只是从异步方法中获取令牌,什么也不做,而是希望设置所有这些仪式,关注工作何时完成,然后继续
  • tl;dr
    只要把async和await看作是不可见的回调,async表示什么时候可以监听,而await就是监听的实际功能。

    在Dart
    async
    中,表示包含
    await
    的代码需要重写。
    async
    /
    await
    只是
    未来的语法糖。然后()
    基本API,在编译和执行之前,代码被重写为这种基于规范的
    未来的
    形式

    因此,
    wait
    不会造成代码阻塞

    还有其他受支持的标记,如发电机的
    *sync
    *async

    另见 -
    -异步
    /
    等待
    的基本语义在F#、VB、C#、Python、Dart、Hack和JavaScript中都是相同的。所以我认为这个问题从其他语言中已经有了足够的答案。但由于它已经被重新打开

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

    不,这样想:

    • “异步”表示“不阻止调用线程”
    • “同步”表示“阻止调用线程”
    在异步方法/函数中,方法/函数可以在
    等待
    点暂停,但暂停时不会阻止调用线程。函数以串行方式(一次一条语句)运行,但异步运行(不阻止调用线程)

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

    这就是它的工作原理。
    await
    使用承诺/未来/任务返回方法/函数,
    async
    将方法/函数标记为能够使用
    await

    这样也可以避免重复的功能

    这在历史上阻止命令式语言时是不可能的。方法/函数要么在调用线程完成之前阻止它,要么不阻止它。它是同步的或异步的

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

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


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

    AFAIK异步和阻塞的区别在于,在一个线程中可以有多个异步进程(其中一个是