Dart: How to return Future<void>
Asked Answered
S

2

38

How can I return Future<void> ?

   Future<void> deleteAll(List stuff){
       stuff.forEach( s => delete(s));   //How do I return Future<void> when loop and all delete Operation are finished?
   }

   Future<void> delete(Stuff s) async {
      ....
      file.writeAsString(jsonEncode(...));
   }

How do I return Future<void> when the forEach loop and all delete Operations are finished?

Scarify answered 31/1, 2020 at 9:20 Comment(2)
@pascal I don't think Giovanni Terlingen answer is correct. See these example DartpadDonnelldonnelly
Thanks I'll check it outScarify
M
33

You don't need to return anything manually, since an async function will only return when the function is actually done, but it depends on how/if you wait for invocations you do in this function.

Looking at your examples you are missing the async keyword, which means you need to write the following instead:

Future<void> deleteAll(List stuff) async {
    stuff.forEach( s => delete(s));
}

Future<void> delete(Stuff s) async {
   ....
   await file.writeAsString(jsonEncode(...));
}

When using Future<void> there is no need to explicitly return anything, since void is nothing, as the name implies.

Also make sure you call deleteAll and writeAsString() using await.

Note: To wait for all delete/foreach invocations to complete, see below answer for more details. In short you will need to put all delete invocations in a Future.wait for that.

Myosotis answered 31/1, 2020 at 9:23 Comment(5)
I want to get notified, when deleteAll and all delete calls are finished, so that I can use delteAll().then(() => refreshUI()). What would be the correct strategy for that?Scarify
delete() is an async function. I forgot to add the async keyword in the code snippet. The implementation of delete() is using getApplicationsDIrectory() which is also an async function.Scarify
This is not correct. try adding print("deleteAll") after stuff.forEach.... And add print("delete") after file.writeAs..... You will see deleteAll printed before printing all delete.Donnelldonnelly
So you can see forEach only called delete function asyncronoslly. it won't wait for completion of delete methodDonnelldonnelly
And also don't forget to add await file.writeAsStringDonnelldonnelly
D
5

You can't do that with forEach.

But you can use Future.wait and .map like this

Future<void> deleteAll(List stuff) {
  return Future.wait(stuff.map((s) => delete(s)));
}

Future<void> delete(Stuff s) async{
  ....
  await file.writeAsString(jsonEncode(...));
}

When to use async keyword:

You can use async when your function uses await keyword inside.

So when to use await keyword:

  1. when you want to get the result from an asynchronous function and want do some logic on the result
Future<int> fetchCountAndValidate() asycn{
  final result = await fetchCountFromServer();
  if(result == null)
    return 0;
  else
   return result;
}
  1. When you want to call multiple asynchronous function
Future<int> fetchTotalCount() asycn{
  final result1 = await fetchCount1FromServer();
  final result2 = await fetchCount2FromServer();
  return result1 + result2;
}

When you don't need async or await:

  1. When you just calling another asynchronous function
Future<int> getCount(){
  //some synchronous logic
  final requestBody = {
    "countFor": "..."
  };
  return fetchCountFromServer(requestBody); //this is an asynchronous function which returns `Future<int>`
}
  1. For some rare cases we doesn't care about the completion of asynchronous function
void sendLogoutSignal(){
  http.post(url, {"username" : "id0001"});
}
Donnelldonnelly answered 31/1, 2020 at 9:29 Comment(1)
For those cases where we don't care about completion, wrap the call in unawaited(). dart.dev/tools/linter-rules/unawaited_futuresBuckling

© 2022 - 2024 — McMap. All rights reserved.