What's the difference between returning void vs returning Future<void>?
Asked Answered
O

1

18

Is there a difference between an async method that returns void, and one that returns Future<void>? It seems that both are valid in Dart:

void main() async {
    await myVoid();
    await myFutureVoid();
}


void myVoid() async {
    // Do something
}


Future<void> myFutureVoid() async {
    // Do something
}

Are they identical?

If so, why is void allowed when for example int is not? The compiler says "Functions marked 'async' must have a return type assignable to 'Future'".

Oppose answered 21/5, 2019 at 18:0 Comment(0)
A
43

void f() and Future<void> f() are not identical. (The presence of the async keyword doesn't actually matter. The async keyword primarily enables the use of the await keyword in the function body.)

void f() declares a function that returns nothing. If it does asynchronous work, then that work will be "fire-and-forget": there is no opportunity for the caller of f to wait for it to finish.

In contrast, Future<void> f() declares a function that returns a Future that the caller can wait for (either by using await or by registering a Future.then() callback). There's no value returned by the asynchronous work, but callers can determine when it is finished.

Functions marked with async usually should return a Future. If you have a function that does asynchronous work that produces an actual value (such as an int), then the caller must wait for that value to be computed before it can be used. That function therefore must return a Future.

As a special case, an async function can return void instead of Future<void> to indicate that it is fire-and-forget.

Arthropod answered 22/5, 2019 at 4:16 Comment(4)
Ah, I think I got it. Just to be clear - if myVoid uses await for all it's async calls (i.e. it basically becomes a sync method), then it is possible for main to wait for myVoid to finish... right? I think that's what got me confused, since I encountered such a function and couldn't figure out why it was returning void instead of Future<void>. Especially what confused me was that IntelliJ hints "Await only futures." - but it is still possible to await the function even though it returns void, just the same as if changing it to Future<void>...Oppose
While it's true that await myVoid(); is legal, it's not the same as await myFutureVoid();. A caller would not be able to wait for myVoid to finish. There is a special case where the Dart VM/runtime recognizes that there are outstanding Futures and won't exit until they complete, and that might make it seem like main is waiting. However, if you did await myVoid(); print('foo');, you would see foo printed before myVoid completes it async work.Arthropod
Hmm, I'm not sure if I understand you correctly - if i did await myVoid(); print('foo'); and myVoid is doing await on all its async operations, wouldn't foo be printed after myVoid returns? That's the case I meant in my previous comment. I made a Gist/Dartpad sample to illustrate what I mean: dartpad.dartlang.org/b1acdb31305a1568cf33dc56e8df763fOppose
Huh. I stand corrected about current behavior. It's supposed to be an error (but isn't yet for backward compatibility reasons). You should avoid awaiting void; it might break in the future (pun not intended). Also see github.com/dart-lang/sdk/issues/28305 and github.com/dart-lang/sdk/issues/33415Arthropod

© 2022 - 2024 — McMap. All rights reserved.