【问题标题】:await without declaring function as async等待而不将函数声明为异步
【发布时间】:2019-02-11 14:57:00
【问题描述】:

实际上在 Dart 中,为了在函数体中使用await,需要将整个函数声明为async

import "dart:async";

void main()  async {
  var x = await funcTwo();
  print(x);  
}

funcTwo() async {
  return 42;
}

如果不将main() 标记为async,此代码将无法工作

Error: Unexpected token 'await'. 

但是,文档说“await 表达式计算 e,然后暂停当前正在运行的函数,直到结果准备好——也就是说,直到 Future 完成”(@987654321 @)

所以,也许我错过了什么,但没有必要强制函数异步?强制执行异步声明的理由是什么?

【问题讨论】:

  • 大多数采用asyncawait的语言都选择了相同的设计:C#、Python、JavaScript、Dart等。他们选择它的原因也一样;请参阅here 了解早期的替代方案集合以及为什么没有选择它们。您的特定问题在Inferring “async” 部分下。

标签: asynchronous dart language-design


【解决方案1】:

async 函数中,await 被重写为使用.then(...) 而不是await 的代码。

async 修饰符将此类函数标记为必须重写的函数,并且支持 await

没有async,你将不得不写

void main() {
  return funcTwo().then((x) {
    print(x);  
  });
}

这是一个非常简单的示例,但是当使用更多异步功能时,重写可能会相当复杂,例如 try/catch, await for(...), ...

【讨论】:

  • 所以它来自实现细节?我想它理论上可以重写为void main() { future = funcTwo(); while (future.notCompleted){} x = future.result; print(x); }
  • 这会导致你的 CPU 变热和电池耗尽;-) Dart 在浏览器中使用 JavaScript 之类的事件队列,而不是忙于等待。
  • 是的,我知道,这个例子是一个巨大的简化。我只是想知道异步是否真的需要在上游传播。
  • Async 是一个用于传递回调的统一 API,就像使用 then(...) 一样。如果您仔细考虑这一点,您会发现无法将其传播到上游。有人讨论过,技术上会有一种方法可以使用多个堆栈,但由于浏览器不支持,Dart 也不支持。
  • “如果没有async,您将不得不编写”部分有点令人困惑,因为您在示例中使用了async
【解决方案2】:

一个问题是await 最初不是 Dart 语言的一部分。为了保持与可能使用await 作为标识符的现有程序的向后兼容性,语言设计者添加了一种机制来明确选择使用新的await 关键字:通过添加(以前无效的)构造来声明函数async.

【讨论】:

    猜你喜欢
    • 2023-03-10
    • 2023-03-13
    • 1970-01-01
    • 2019-11-28
    • 2019-06-16
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    相关资源
    最近更新 更多