Dolphin
Dolphin

Reputation: 39095

how to invoke async function in sync function in flutter

Is it possible to invoke async function in flutter sync function without add the async keyword to parent function? I want to invoke the async function like this:

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

I could not add async keywords in the function getEventsForDay because the outer component did not allow. But I still need to wait the getTasksByRangeDate return to load some initial data. what should I do to invoke an async function without add async keywords in parent function? BTW, this is the full code:

  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;
  }

I have already tried using then like this:

 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;
  }

seems could not return the task list to outer layer funciton. I have tried like this:

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;
  }

but the taskResult result always be Null.

Upvotes: 3

Views: 5505

Answers (2)

Jack&#39;
Jack&#39;

Reputation: 2526

Yes, it is possible to call async code from a synchronous function !

It will just be executed on another thread.

Method 1 (Clean)

What we usually do is create an async function and call it from the synchronous one :

import 'dart:async';

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

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

Method 2 (Fast)

import 'dart:async';

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

PS : If you don't want to call unawaited(), you can just remove it, but it is not recommended. After you remove it, it would just look like this :

() async {
      // Do something asyncrhronous
}.call();

Conclusion

Try the code on the DartPad !

You can see that we don't use async in the method main() for both cases. I will let you choose which one you prefer. I personally use the Method 2 for debugging purposes.

Upvotes: 4

lrn
lrn

Reputation: 71873

You cannot.

A function always returns "synchronously" when it's called. An async function does too, it just returns a Future which will complete at some later point.

The point of an asynchronous function is that it doesn't have a result to return immediately.

So, when your synchronous function calls an asynchronous function, and wants to return the result of that, it cannot. The result does not exist yet, at the time where you want to return it.

You must wait for the asynchronous function's future to complete in order to get the result. That means returning from the synchronous function, back to the event loop, so that other parts of the asynchronous computation gets to run.

TL;DR: If your function depends on an asynchronous function's result, your function must also be asynchronous. Anything else does not even make sense, it requires return a result before it event exists.

Upvotes: 4

Related Questions