Flutter/Dart Async Not Waiting

14,700

To await something you have to call the await keyword on a future instead of .then

final result = await future;
// do something

instead of

future.then((result) {
  // do something
});

If you really want to use .then then you can await the generated future:

await future.then((result) {
  // do something
});

Just ensure that when using nested asynchronous calls that the async keyword is used on each:

await future.then((result) async{
    // do something
    await future.then((result_2) {
       // do something else
    });
});
Share:
14,700
Topazoo
Author by

Topazoo

Updated on July 18, 2022

Comments

  • Topazoo
    Topazoo almost 2 years

    I'm building my first Flutter application and I've run into a bit of an async issue.

    When my application executes I'd like it to ask for permissions and wait until they are granted. My main() function looks like this:

    import 'permission_manager.dart' as Perm_Manager;
    
    void main() async
    {
      //Ensure valid permissions
      Perm_Manager.Permission_Manager pm = Perm_Manager.Permission_Manager();
      var res = await pm.get_permissions();
      print(res);
    
      return runApp(MyApp());
    } 
    

    The Permission Manager class' get_permissions() function uses the Flutter Simple Permissions package to check and ask for permissions.

    import 'package:simple_permissions/simple_permissions.dart';
    import 'dart:io' as IO;
    import 'dart:async';
    
    class Permission_Manager {
      /* Get user permissions */
    
      Future<bool> get_permissions() async
      {
        //Android handler
        if (IO.Platform.isAndroid)
        {
            //Check for read permissions
            SimplePermissions.checkPermission(Permission.ReadExternalStorage).then((result)
            {
              //If granted
              if (result)
                return true;
    
              //Otherwise request them
              else
              {
                SimplePermissions.requestPermission(Permission.ReadExternalStorage)
                .then((result)
                {
                  // Determine if they were granted
                  if (result == PermissionStatus.authorized)
                    return true;
                  else
                    IO.exit(0); //TODO - display a message
                });
              }
            });
        }
    
        else
          return true;
      }
    }
    

    When I run the application it does not wait for the function to complete as intended and prints the value of "res" before the Future is updated.

    Launching lib\main.dart on Android SDK built for x86 in debug mode...
    Built build\app\outputs\apk\debug\app-debug.apk.
    I/SimplePermission(15066): Checking permission : android.permission.READ_EXTERNAL_STORAGE
    I/flutter (15066): null
    I/SimplePermission(15066): Requesting permission : android.permission.READ_EXTERNAL_STORAGE
    

    The Future returns a value midway through the function! Does anyone know what I'm doing wrong?

  • Topazoo
    Topazoo over 5 years
    "await" is used in the main() function which calls the asynchronous function. Notwithstanding I was under the impression that "then" and "await" while syntactically different (with "then" running a function after completion) they operated the same way.
  • Rémi Rousselet
    Rémi Rousselet over 5 years
    No they don't. You really have to use await
  • Topazoo
    Topazoo over 5 years
    From the Dart documentation (dartlang.org/tutorials/language/futures): "To suspend execution until a future completes, use await in an async function (or use then())." But despite this I did use await in my main() function to no avail.
  • Rémi Rousselet
    Rémi Rousselet over 5 years
    that makes your async flag on get_permissions useless.
  • Rémi Rousselet
    Rémi Rousselet over 5 years
    Once is not enough. you need more then just one await in your example
  • Topazoo
    Topazoo over 5 years
    The application requires read permissions for any functionality but the Simple Permissions plugin operates asynchronously. Specifically, when opening the application reads all files in the Downloads directory. This solution stops the application from reading the directory until permissions are granted. If there's a way to use the plugin synchronously that would be ideal, but I don't think it's possible.
  • Rémi Rousselet
    Rémi Rousselet over 5 years
    I'm not saying the code doesn't work, but that the syntax is not the right one.
  • Topazoo
    Topazoo over 5 years
    The docs for reference (pub.dartlang.org/packages/simple_permissions#-readme-tab-). Running the code without the async flag and returning a non-Future bool produces the same results as seen in the initial question (due to the plugin code running asynchronously). Is there another way to do it?
  • Topazoo
    Topazoo over 5 years
    I don't think you can await the generated future. The generated future is local to the callback function run by then() and doing something like "await SimplePermissions.checkPermission(Permission.ReadExternalSto‌​rage).then((result) { ..." generates an error. It's true that you could return the generated future from the callback, but since the plugin doesn't return boolean values you'd need to rewrite most of the function in main()
  • Topazoo
    Topazoo over 5 years
    Ah you are correct! My apologies. You can indeed await the result of then. Unfortunately in this case I am returning values and it still doesn't work :(. I/SimplePermission(18817): Checking permission : android.permission.READ_EXTERNAL_STORAGE I/flutter (18817): Instance of 'Future<bool>' I/SimplePermission(18817): Requesting permission : android.permission.READ_EXTERNAL_STORAGE
  • Topazoo
    Topazoo over 5 years
    NEVERMIND!! Declaring the first then() function as asynchronous (since the second is nested) did the job. Thanks for all your help Rémi.
  • Rémi Rousselet
    Rémi Rousselet over 5 years
    Perfect. I'd still recommend you to not use then though. It's harder to read and doesn't bring anything compared to the flattened async/await
  • Roxx
    Roxx about 4 years
    @RémiRousselet can you help me with this question. I am also facing similar issue. stackoverflow.com/questions/62502334/…