1

What is the difference between:

Future<void>, async, await, then, catchError

Future<void> copyToClipboard(BuildContext context, String text) async {
  await Clipboard.setData(ClipboardData(text: text))
      .then((_) => showSnackBar(context, 'Copied to clipboard'))
      .catchError((Object error) => showSnackBar(context, 'Error $error'));
}

void, async, await, then, catchError

void copyToClipboard(BuildContext context, String text) async {
  await Clipboard.setData(ClipboardData(text: text))
      .then((_) => showSnackBar(context, 'Copied to clipboard'))
      .catchError((Object error) => showSnackBar(context, 'Error $error'));
}

void, then, catchError

void copyToClipboard(BuildContext context, String text) {
  Clipboard.setData(ClipboardData(text: text))
      .then((_) => showSnackBar(context, 'Copied to clipboard'))
      .catchError((Object error) => showSnackBar(context, 'Error $error'));
}

All methods work. If I'm using then and catchError, do I still need to wrap the code in an async function?

Which is the recommended way?

TechAurelian
  • 5,561
  • 5
  • 50
  • 65
  • you use `async` only when `await` is used in function body - and in that case `async` function shouldn't return `void` as there is no way to check when the function completes - you should return a `Future` (even if its `Future`) – pskink Mar 07 '20 at 09:21
  • 1
    and when using `async` / `await` stuff there is a little need for using Future` API - `then()` and `catchError()` - for more read https://dart.dev/codelabs/async-await and https://dart.dev/guides/libraries/futures-error-handling – pskink Mar 07 '20 at 09:42

1 Answers1

3

First of, the concept of async/await and then is basically the same. Many people say that async/await is the more elegant way to deal with Promises (because it looks more structured). What both ideas do is: "Do something and once it is done, do something else".

Regarding Future<void> copyToClipboard(BuildContext context, String text) async {...}: Here you are returning a Promise from your function. Meaning, that you can call the function from somewhere else with

await copyToClipboard(context,"Text"); 
print("Done");

You can, however also return the Promise itself (and then handle it wherever you call that function):

Future<void> copyToClipboard(BuildContext context, String text) async {
  return Clipboard.setData(ClipboardData(text: text));    
}
void somewhereElse() async{
 await copyToClipboard(context,"Text"); // (1)
 print("Copied"); //Happens after (1)
}

So if you are using then, you will put the following instructions into the corresponding function called by it (as seen in your 3rd snippet). Solving the 2nd snippet with async would looke like this:

void copyToClipboard(BuildContext context, String text) async {
  await Clipboard.setData(ClipboardData(text: text));// (1)
  showSnackBar(context, 'Copied to clipboard')); // (2) This will only be called when (1) has completed
}

If this instruction throws an error, you can wrap it into a try/catch block:

void copyToClipboard(BuildContext context, String text) async {
  try{
      await Clipboard.setData(ClipboardData(text: text));// (1)
      showSnackBar(context, 'Copied to clipboard')); // (2) This will only be called when (1) has completed
  }catch (error) {
     print(error.message);
  }
}

If you prefer then/wait or async/await is up to you. I would recommend async/await. Keep in mind that when using async/await, you need to put the async keyword into the signature of the function, so functions calling this function are aware, that calling it may take a while and wait for it.

Thomas
  • 2,375
  • 2
  • 17
  • 32
  • Thank you for your answer. In your latest code sample, shouldn't the async function return `Future` instead of `void`? – TechAurelian Mar 07 '20 at 09:12
  • Nope, because you are not returning anything. when you have a future as the return type, you also need to return a future, as seen in the 2nd block. – Thomas Mar 07 '20 at 09:15