如何在Flutter中在同步函数中调用异步函数

3

在Flutter中,是否可以在同步函数内调用异步函数而不将async关键字添加到父函数中?我想像这样调用异步函数:

 void getEventsForDay(DateTime day) {
    var result = await TaskProvider.getTasksByRangeDate(monthStartMilliseconds, monthEndMilliseconds); 
 }

由于外部组件不允许,我无法在函数getEventsForDay中添加async关键字。但是我仍然需要等待getTasksByRangeDate返回一些初始数据后才能加载。那么,在不在父函数中添加async关键字的情况下如何调用异步函数呢?顺便说一句,这是完整代码:

  List<TodoTask> getEventsForDay(DateTime day) {
    int monthStartMilliseconds = DateTimeUtils.startOfMonthMilliseconds(DateTime.now());
    int monthEndMilliseconds = DateTimeUtils.endOfMonthMilliseconds(DateTime.now());
    var result = await TaskProvider.getTasksByRangeDate(monthStartMilliseconds, monthEndMilliseconds);
    tasks.addAll(result);
    buildHashMap(result);
    final DateFormat formatter = DateFormat('yyyy-MM-dd');
    String dateString = formatter.format(day);
    List<TodoTask> dayTodoTask = taskMap[dateString] ?? [];
    return dayTodoTask;
  }

我已经尝试过像这样使用“then”:

 List<TodoTask> getEventsForDay(DateTime day) {
    int monthStartMilliseconds = DateTimeUtils.startOfMonthMilliseconds(DateTime.now());
    int monthEndMilliseconds = DateTimeUtils.endOfMonthMilliseconds(DateTime.now());
    TaskProvider.getTasksByRangeDate(monthStartMilliseconds, monthEndMilliseconds).then((value) => {getTasks(value, day)});
  }

  List<TodoTask> getTasks(List<TodoTask> tasks, DateTime day) {
    tasks.addAll(tasks);
    buildHashMap(tasks);
    final DateFormat formatter = DateFormat('yyyy-MM-dd');
    String dateString = formatter.format(day);
    List<TodoTask> dayTodoTask = taskMap[dateString] ?? [];
    return dayTodoTask;
  }

似乎无法将任务列表返回给外层函数。我尝试了以下方法:

List<TodoTask> getEventsForDay(DateTime day) {
    var taskResult;
    int monthStartMilliseconds = DateTimeUtils.startOfMonthMilliseconds(DateTime.now());
    int monthEndMilliseconds = DateTimeUtils.endOfMonthMilliseconds(DateTime.now());
    TaskProvider.getTasksByRangeDate(monthStartMilliseconds, monthEndMilliseconds)
        .then((value) => {() => taskResult = getTasks(value, day)});
    return taskResult ?? [];
  }

  List<TodoTask> getTasks(List<TodoTask> tasks, DateTime day) {
    tasks.addAll(tasks);
    buildHashMap(tasks);
    final DateFormat formatter = DateFormat('yyyy-MM-dd');
    String dateString = formatter.format(day);
    List<TodoTask> dayTodoTask = taskMap[dateString] ?? [];
    return dayTodoTask;
  }

但是taskResult的结果总是为空。

2个回答

3
是的,可以从同步函数调用异步代码!
它将在另一个线程上执行。
方法1(简洁):
通常我们会创建一个异步函数并从同步函数中调用它:
import 'dart:async';

void main() {
  
  doSomething();
  
  print('Hello');
  
}

Future doSomething() async {
  await Future.delayed(const Duration(seconds: 2))
        .then((_) => print("Oops I am late"));
}

方法二(快速)
import 'dart:async';

void main() {
  
  unawaited(() async {
    await Future.delayed(const Duration(seconds: 2))
        .then((_) => print("Oops I am late"));
  }.call());
  
  print('Hello');
  
}

PS:如果您不想调用unawaited(),可以将其删除,但不建议这样做。删除后,它看起来就像这样:
() async {
      // Do something asyncrhronous
}.call();

结论

DartPad上尝试这段代码!

您可以看到,我们在两种情况下都没有在main()方法中使用async。 我会让你选择哪一个你喜欢。我个人使用方法2进行调试。


2

你无法这样做。

当调用函数时,函数总是“同步”返回结果。异步函数也是如此,它只是返回一个将在稍后完成的“Future”。

异步函数的关键在于它没有立即返回结果。

因此,当同步函数调用异步函数并希望返回其结果时,它无法这样做。在您想要返回结果的时间,结果尚不存在。

您必须等待异步函数的future完成才能获得结果。这意味着从同步函数返回到事件循环,以便运行异步计算的其他部分。

简而言之:如果您的函数依赖于异步函数的结果,则您的函数也必须是异步的。其他任何方式都没有意义,因为它需要在结果实际存在之前返回结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接