Search code examples
asynchronousdartfuturevoidsynchronous

Dart - Distinguish between sync and async void callbacks


Suppose we have the following method:

Future<String> foo(void callback()) async{
    ...
    callback();
    ...
}

Then the callback is allowed to be either sync or async when defined. Is there a clean way to await it if it is async? Now if I await it here I get this warning from IDE:

'await' applied to 'void', which is not a 'Future'


Solution

  • You can't. The whole point of making an async function return void instead of Future<void> is so that the function is "fire-and-forget" and so that the caller can't wait for it to complete.

    If you want to allow your foo function to take asynchronous functions as arguments, then its parameter should be a Future<void> Function() instead. That way callers can easily adapt a synchronous function with an asynchronous wrapper. (The reverse is not possible.)

    Alternatively you could make the callback parameter return a FutureOr<void>:

    Future<String> foo(FutureOr<void> Function callback) async {
        ...
        await callback();
        ...
    }
    

    or if you don't want an unnecessary await if callback is synchronous:

    Future<String> foo(FutureOr<void> Function callback) async {
        ...
        if (callback is Future<void> Function) {
          await callback();
        } else {
          callback();
        }
        ...
    }