为什么等待'需要' async'在函数定义中

时间:2017-07-03 22:46:54

标签: 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;
    ...
  }
}

这对我没有意义。如果某个函数正在等待异步函数完成,那么它是否会被视为阻塞?为什么JS和Dart要求它被标记为异步?这不是相反的吗?

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

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

4 个答案:

答案 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#中最不幸的关键字选择。如果您将其视为awaitresume after,则yield then resume after更易理解。当执行遇到await时,它会挂起当前函数,返回其调用者。一旦等待的Task完成,当调用者需要结果{来自await表达式await时,执行将在{{1}}之后恢复。

答案 3 :(得分:-3)

这是对“引擎盖下”发生的事情的一个基本误解,我假设javascript async / await实现镜像(至少在概念上)是.NET世界的镜像(起源于F#)。 / p>

本质:

  1. 各种“工作单元”“令牌”(在C#a JS in Promise中的任务)表示任务的完成,并且可以选择返回值。
  2. “异步”方法用async标记,以向编译器/解释器/运行时指示该方法将返回所述令牌,并且可能也会消耗一些令牌。
  3. 运行它的东西,将(在C#的情况下),重写狡猾的代码基本上做以下事情:
    1. 启动异步方法
    2. 执行标准普通代码
    3. 遇到“令牌”提供方法
    4. 调用它,抓住令牌
    5. 设置代码可以跳回到以后的地方
    6. 令牌是否完整?如果是这样,请继续,如果没有,请设置回调以使运行时回到此处
    7. 在这个扩展的上下文中,关键字是有意义的:

      1. async(hronous) - 执行某项任务的方法,可以花费不确定的时间,可以等待。
      2. await - 表示您不是仅仅从异步方法中获取令牌而不对其执行任何操作,而是实际上想要设置所有这些仪式,并在工作完成时进行监听,并继续进行。
      3. TL;博士

        只需考虑async并等待不可见的回调,async指示何时可以监听某些内容,并且await实际上是在监听。