When do I need to state the return type of an async function as a future object?
Yes, using the async keyword will make the function automatically return a Future.
It is always better to explicitly declare the return type of a function even for void functions, if not, the compiler will interpret the function as having a dynamic return type.
It will also help/make it easier for the reader to know the return type of the function.
Also, you need to wrap your object in a Future in an async function like so:
Future<Object> getObject() async { final object = await timeConsumingTask(); return object;}
If you write it like this without wrapping it:
Object getObject() async { final object = await timeConsumingTask(); return object;}
The compiler throws the error: Functions marked 'async' must have a return type assignable to 'Future'.
For void functions, it seems that you do not have to wrap the return type in a Future, so something like this is fine:
void doSomething() async { await timeConsumingTask(); print('done');}
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 finishFuture<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
.