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
.