Let's consider a method gatherNewsReports() which only returns a Future<String>. The string value of the Future from gatherNewsReports. Implementation of gatherNewsReports.
// Imagine this is a slow method. Takes time to finish
Future<String> gatherNewsReports() => Future.delayed(Duration(seconds: 1), () => news);
We will go through all possible combinations of method call with Future and async. The method I am going to make is called getDailyNewsDigest
Option-1:
One definition of the method might be as with Future and async given in method call:
Future<String> getDailyNewsDigest() async {
var str = await gatherNewsReports();
print(str);
return str;
}
Remember that gatherNewsReports() which returns a Future<String>. We are just returning whatever gatherNewsReports returns.
Usage:
main() async {
await getDailyNewsDigest();
print('call done');
}
Output:
<gathered news goes here>
call done
Comments: This seems straight forward. You just call the method and await on it. Remember we are using await keyword when calling getDailyNewsDigest from the main method. So, unless we pass 1 second, i.e, the duration of time it requires the Future to execute. If we didn't use the await keyword then the output sequence will be reversed.
Option 2
One definition of the method might be as with Future given and async NOT given in method call:
Future<String> getDailyNewsDigest() {
var str = await gatherNewsReports();
print(str);
return str;
}
This is not valid because you can't call a method with await, in this case gatherNewsReports. This is invalid.
Option-3
We define the method might be with Future NOT GIVEN and async given in method call. Since the return type is going to be void we will not return anything (N.B: If we try to return anything other than a Future or a void then we get an error):
void getDailyNewsDigest() async {
var str = await gatherNewsReports();
print(str);
}
This is a valid method definition. Now, since the method is declared as void we can't await on the main method. The updated main method.
main() async {
getDailyNewsDigest(); // We can't await on it since return is void
print('call done');
}
Output:
call done
<gathered news goes here>
As you can see since the method getDailyNewsDigest is not called without await the output is reversed. We are no longer waiting for the getDailyNewsDigest to finish.
Option-4
We define the method might be with Future<Void> instead of Future<String> and async given in method call:
Future<void> getDailyNewsDigest() async {
var str = await gatherNewsReports();
print(str);
return;
}
Now in our main method we can use the await keyword again for calling 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');
}
These are 4 combinations I can think of.
As for this:
But my instructor kind of confused me, sometimes she had a future as
the return type and another time she didn't put it and they were both
async functions.
Declaring a method with either Future means you can await on it, declaring it with void means you can't await in it. You can of course choose not to await on a Future if you don't care to do anything with the output of the Future. If you write your code in such a way that you don't want anyone to depend on the output of the method, i.e, the Future we would otherwise return from the method will be handle d by itself, all we care about is firing-it-and-continue with our work; in that case we should define our method with return type void.