【问题标题】:Return type of void async function in DartDart 中 void 异步函数的返回类型
【发布时间】:2019-11-19 17:09:35
【问题描述】:

在 Dart 中,如果你有一个不返回任何内容的异步函数,它应该返回 Future<void> 还是简单地返回 void?两者似乎都有效,但为什么呢?

void foo() async {
  print('foo');
}

Future<void> bar() async {
  print('bar');
}

void main() async {
  await foo();
  await bar();
  print('baz');
}

编译没有错误或警告并打印

foo
bar
baz

【问题讨论】:

    标签: dart


    【解决方案1】:

    在您的代码中,foo()bar() 两个函数都没有返回任何内容,因此任何函数返回类型对这两个函数都有效 例如:

    void/T/Future<T>... foo() async {
      print('foo');
    }
    
    Future<void>/T/Future<T>... bar() async {
      print('bar');
    }
    

    这里,

    await foo();
    await bar();
    

    await 只是等待这些异步函数的执行完成。由于没有返回类型,await 在这里没有任何目的(冗余),所以这是也不应该是编译错误。


    区别在于Future&lt;void&gt;给你函数的执行信息,比如执行完成的时候,它还允许你指定函数执行时要做什么,使用@ 987654327@和bar().whenComplete(...)

    虽然foo() 函数返回voidvoid 不包含像Future&lt;void&gt; 这样的任何信息。如果您尝试await bar(),它会将Future 对象从Future&lt;void&gt; 转换为void


    Future 只是一个容器,await 在异步“任务”完成后返回值。如果没有awaitFuture 对象会为您提供有关它们返回的函数的执行信息。

    【讨论】:

      【解决方案2】:

      感谢其他答案 - 他们对我来说有点不清楚,所以我将在 DartPad 上进行实验后添加一些说明:

      1. 无论返回类型如何,不从函数返回值都不是错误甚至警告!。这种疯狂大概是继承自 Javascript。

      2. 如果您不从函数返回,它会隐式返回 null。除了这些情况:

        • 如果返回类型为void,则不返回值(使用表达式的结果是编译器错误)。
        • 如果函数是async
          • 如果返回类型为void,则不能使用函数的结果,但仍然可以await,但不能使用await表达式的结果,也不能使用Future的任何方法.
          • 如果返回类型为Future&lt;void&gt;,则返回Future&lt;void&gt; 的实例。你可以await它,并调用Future的方法,例如.then((void v) { ... });。但是您不能使用await 的结果(因为它是void)。
          • 如果返回类型为 Future&lt;T&gt;,则返回解析为 nullFuture&lt;T&gt; 实例。

      所以基本上,如果要允许调用者使用Future 方法,则需要将返回类型注释为Future&lt;void&gt;。如果你只是想让他们能够await的功能,你只需要void。但是,由于您可能事先不知道,我怀疑始终使用 Future&lt;void&gt; 是个好主意。

      这是一个展示可能性的示例:

      // Compilation error - functions marked async must have a 
      // return type assignable to 'Future'
      // int int_async() async {
      // }
      void void_async() async {
      }
      Future<void> future_void_async() async {
      }
      Future<int> future_int_async() async {
      }
      int int_sync() {
      }
      void void_sync() {
      }
      Future<void> future_void_sync() {
      }
      Future<int> future_int_sync() {
      }
      
      
      void main() async {
        // print('${void_async()}'); // Compilation error - expression has type void.
        print('future_void_async: ${future_void_async()}');
        print('future_int_async: ${future_int_async()}');
        // print('${await future_void_async()}'); // Compilation error.
        await future_void_async();
        future_void_async().then((void v) {
          print('ok');
        });
        await void_async();
        // void_async().then((void v) { // Compilation error.
        //   print('ok');
        // });
        print('await future_int_async: ${await future_int_async()}');
        print('int_sync: ${int_sync()}');
        // print('${void_sync()}'); // Compilation error - expression has type void
        print('future_void_sync: ${future_void_sync()}');
        print('future_int_sync: ${future_int_sync()}');
      }
      

      打印出来

      
      future_void_async: Instance of '_Future<void>'
      future_int_async: Instance of '_Future<int>'
      ok
      await future_int_async: null
      int_sync: null
      future_void_sync: null
      future_int_sync: null
      

      【讨论】:

      • 在具有返回类型的函数中不返回值是一个警告。
      • 这是对await 一个async 函数的(短绒)警告,它被声明为返回voiddart-lang.github.io/linter/lints/await_only_futures.html 这就是我找到这篇文章的方式。从我目前所知道的一切来看,似乎等待异步调用,但它令人困惑,所以也许不要使用它。
      【解决方案3】:

      Future 只是尚未完成底层功能的Object 的表示,因此是供以后使用的“承诺”。当您使用Future&lt;void&gt; 时,无论如何都没有Object 可以返回,因此无论您使用void 还是Future&lt;void&gt; 都没有关系。 (该函数不返回任何内容,因此返回类型无论如何都是占位符。)

      但是... Future&lt;void&gt; 可用于监听器,并检查事情何时完成,每个Future 都可以。这意味着您可以使用Future 的侦听器来检查运行Future&lt;void&gt; async 函数的完成或错误,但不能检查void async 函数。因此,在某些情况下,将Future&lt;void&gt; 提供为比void 作为返回类型更好。

      【讨论】:

        猜你喜欢
        • 2015-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-08
        • 2018-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多