Future/async/await in Dart

断了今生、忘了曾经 提交于 2019-12-29 05:46:05

问题


I have a function loadData that loads some text from a file:

Future<String> loadAsset() async {
  return await rootBundle.loadString('assets/data/entities.json');
}

The loadString method is from Flutter SDK, and is asynchronous.

The loadAsset method is then called in another method, that must me marked as async, since loadAsset is async and I need to use await:

Future<List<Entity>> loadEntities() async {
  String jsonData = await loadAsset();
  return parseData(jsonData);
}

The parseData method is not async, it receives a String, parse it, and return a list of objects:

List<Entity> parseData(String jsonString) {
  ...
}

But since loadEntities must be marked with async, this requires that it returns a Future, but in practice, it's not a Future because since I use await, it awaits for the loadAsset method to finish, then call the parseData funcion using the result.

This easily turns into a snowball of async call, because every method that uses loadEntities must be marked as async too.

Also, I can't use loadEntities in a class constructor, because the constructor should be marked as async, which is not allowed in Dart.

Am I using the async/await pattern in Dart wrong? How could I use the loadEntities method in a class constructor?


回答1:


No, async is contagious and there is no way to go back from async to sync execution.

async/await is only syntactic sugar for methodThatReturnsFuture().then(...)

Marking a method with async is only to allow you to use await inside its body. Without async you would still need to return a Future for calling code to only execute after the result of loadAsset() becomes available.




回答2:


You can use the Future returned from the async call directly. This would look something like this:

class HasAsync {
  HasAsync() {
    asyncFunction().then((val) {
      print(val);
    });
  }

  Future<int> asyncFunction() async {
     int val = await otherFunction();
     return val;
  }
}

You just can't use await within the non-async function.

As you've tagged this with 'flutter', I'm going to guess this is within a flutter app. If that's the case look at the docs for FutureBuilder - it might help with what you're trying to do.




回答3:


Just a correction: async methods are NOT contagious. The Test constructor calls the async method sayHello. This demonstrates how to have a ctor make an async call when its not allowed to be declared async. The main method is marked async simply so that the application doesn't shutdown before sayHello completes. Its not an intrinsic requirement.

class Test
{
  Test()
  {
    sayHello();
  }

  void sayHello() async
  {
    await Future.delayed(Duration(seconds: 4) , () => print("Hello"));

    print("We said hello");
  }

}

  void main() async
  {

    doTest();

  // wait for hello to be output
    await Future.delayed(Duration(seconds: 6) , ()  {});

    print("Ending");
  }

  void doTest()
  {
        Test();
  }


来源:https://stackoverflow.com/questions/49537996/future-async-await-in-dart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!