Home > OS >  using await to retrieve data
using await to retrieve data

Time:03-26

I don't really understand how the await/async mechanism (in dart but I guess the question is relevant for any language actually). I'm using the sqfentity library to manage a small database.

this lib is providing a select().toList() function which will query some DB rows and returns it as a list of object.

the returned function is actually returning a Future<List> allowing to run the query asynchronously.

I'm working with local DB so I'm not really concerned by access time issues, so I'd like to write a function returning a list,once the query has finished:

    List<Event> get_list() async{
      return await Event()
      .select()
      .toList()
    }

The problem is that an async function must return a Future<> object. However, if I understand well, the await will "wait" for the toList() function to finishes before returning, so I don't understand why I can't just return the List object.

In order to do my job, I used the fact that in dart, parameters are passed by reference, so I wrote some intermediate function

void fillList(List<Event> lst){
   lst.addAll(await Event()
      .select()
      .toList())
}
List<Event> get_list() {
      List<Event> lst;
      fillList(lst);
      return lst;
    }

which seems really not natural and probably a wrong way to do things. Any explanation on how to deal with await in dart ?

thanks!

CodePudding user response:

I am not very sure if I understood the question, but it depends on the return type of Event().select();. If it returns a Future, then you need to use the async/await combination, or the then callback. Otherwise, you can just return a list of Event directly.

You can also do something like:

    List<Event> get_list(){
      final List<Event> events = [];

// If Event().select() returns a Future
      Event()
      .select().then((result){
         events.addAll(result.toList());
      });

      return events;
    }

But the issue with this is that while Event().select() is still loading, the function will return an empty list, then when items are loaded, the function will come back and fill the list with the returned items. That's why something like:

    Future<List<Event>> get_list() async{
      final events = await Event().select();
      return events.toList();
    }

Is kind of better because if you want for example to show a spinner while items are loading, you can do that, also you can easily catch errors.

CodePudding user response:

However, if I understand well, the await will "wait" for the toList() function to finishes before returning, so I don't understand why I can't just return the List object.

When you do:

Future<Result> foo() async {
  var intermediateResult = await someAsynchronousOperation();
  var result = doOtherStuff(intermediateResult);
  ...
  return result;
}

await provides the appearance of pausing execution of foo until someAsynchronousOperation() completes. It does not pause your entire program. The point of an asynchronous operation is to allow the rest of your program to continue executing while you are waiting for it to complete. This allows your program to continue to respond to user input.

Whenever you use await, it's actually syntactic sugar for returning a Future:

Future<Result> foo() {
  return someAsynchronousOperation().then((someIntermediateResult) {
    var result = doOtherStuff(intermediateResult);
    ...
    return result;
  });
}

foo() calls someAsynchronousOperation() (which itself returns a Future), registers a .then() completion callback on it to execute doSomeOtherStuff() later. foo() then immediately returns the resulting Future to its own caller.

void fillList(List<Event> lst){
   lst.addAll(await Event()
      .select()
      .toList())
}
List<Event> get_list() {
      List<Event> lst;
      fillList(lst);
      return lst;
    }

That will not work.

  1. await can be used only in a function declared with async.
  2. Because fillList depends on a Future, it is inherently asynchronous. However, by declaring it to return void instead of a Future, it is impossible for callers to be notified when fillList completes.
  3. Once you fix fillList to return a Future, get_list needs to wait for that Future to complete before returning lst. Since get_list would need to depend on a Future, it too is inherently asynchronous. (Asynchronous functions are contagious.)
  • Related