我何时需要将异步函数的返回类型声明为将来的对象?

时间:2019-06-10 04:00:49

标签: flutter dart async-await future

我正在上一堂关于使用dart进行异步编程的课程,但是由于某种原因,我感到有些困惑。我想我了解在可能需要一些时间时应如何使用异步函数的概念,因此,您可以使用异步函数代替阻塞和冻结您的应用程序,以便执行下一个代码块或方法以及何时使用异步函数完成或准备执行。 (如果我的理解有误,请告诉我)

但是,我并没有真正了解Future <>部分。我知道它可以用作异步函数的返回类型,因为从本质上讲,您是说该函数现在返回一个将来的对象,但是让它在完成后返回它。但是我的老师有点困惑我,有时候她有一个返回类型的未来,而另一次她没有放它,它们都是异步函数。因此,现在我正在努力了解何时必须明确声明Future返回类型,即使该类型为空?还不只是使用异步并等待函数已经创建了将来的对象,无论如何?非常感谢任何澄清。

2 个答案:

答案 0 :(得分:2)

是的,使用async关键字将使该函数自动返回Future。

最好始终明确声明函数的返回类型,即使对于void函数也是如此,否则,编译器会将函数解释为具有动态返回类型。

它还将帮助/使读者更容易地知道函数的返回类型。

此外,您还需要将异步操作中的对象包装在Future中,如下所示:

Future<Object> getObject() async {
  final object = await timeConsumingTask();
  return object;
}

如果您不这样包装就这样写:

Object getObject() async {
  final object = await timeConsumingTask();
  return object;
}

编译器抛出错误:Functions marked 'async' must have a return type assignable to 'Future'.

对于void函数,您似乎不必将返回类型包装在Future中,因此可以这样:

void doSomething() async {
  await timeConsumingTask();
  print('done');
}

答案 1 :(得分:0)

让我们考虑一种方法gatherNewsReports(),该方法仅返回Future<String>FuturegatherNewsReports的字符串值。 gatherNewsReports的实现。

// Imagine this is a slow method. Takes time to finish
Future<String> gatherNewsReports() => Future.delayed(Duration(seconds: 1), () => news);

我们将介绍方法调用与Futureasync的所有可能组合。我要制作的方法称为getDailyNewsDigest

选项1:

方法的一种定义可能与方法调用中给出的Futureasync相同:

Future<String> getDailyNewsDigest() async {
  var str = await gatherNewsReports();
  print(str);
  return str;
}

请记住,gatherNewsReports()返回了Future<String>。我们只是返回gatherNewsReports返回的值。

用法:

main() async {
  await getDailyNewsDigest();
  print('call done');
}

输出:

<gathered news goes here>
call done

评论:这似乎很简单。您只需调用该方法并等待它即可。请记住,从await方法调用getDailyNewsDigest时,我们使用的是main关键字。因此,除非我们通过1 second,即需要Future执行的持续时间。如果我们不使用await关键字,那么输出顺序将相反。

选项2

方法的一种定义可能与方法调用中给定的Futureasync 相同。

Future<String> getDailyNewsDigest() {
  var str = await gatherNewsReports();
  print(str);
  return str;
}

这是无效的,因为您无法使用await(在本例中为gatherNewsReports)中调用方法。 这无效

选项3

我们定义方法可能与方法调用中指定的Future NOT GIVEN async一起使用。由于返回类型将为void,因此我们将不会返回任何内容(注意:如果我们尝试返回Futurevoid以外的任何内容,则会收到错误消息):

void getDailyNewsDigest() async {
  var str = await gatherNewsReports();
  print(str);
}

这是有效的方法定义。现在,由于该方法被声明为void,因此我们无法在await方法上main。更新的main方法。

main() async {
  getDailyNewsDigest(); // We can't await on it since return is void
  print('call done');
}

输出:

call done
<gathered news goes here>

如您所见,由于在没有getDailyNewsDigest的情况下不会调用方法await,所以输出是相反的。我们不再等待getDailyNewsDigest完成。

选项4

我们定义该方法可能使用Future<Void>,而不是方法调用中给出的Future<String>async

Future<void> getDailyNewsDigest() async {
  var str = await gatherNewsReports();
  print(str);
  return;
}

现在,在我们的主要方法中,我们可以再次使用await关键字来调用getDailyNewsDigest

main() async {
  await getDailyNewsDigest(); // We can await on it since return is Future<Void> but don't care on the output since it returns nothing
  print('call done');
}

这些是我可以想到的4种组合。

对此:

  

但是我的教练有点困惑我,有时候她有一个未来   返回类型,还有一次她没有输入,他们俩都是   异步功能。

使用Future声明一个方法意味着您可以等待它,而使用void声明一个方法意味着您不能在其中await。如果您不愿意对await的输出做任何事情,当然可以选择不在FutureFuture。如果您以不希望任何人依赖该方法输出的方式来编写代码,即,否则将从该方法返回的Future本身将被处理d,我们关心的是关于继续进行我们的工作;在这种情况下,我们应该使用返回类型void定义我们的方法。