Dart Future tutorial with examples
Tags: dart, flutter, programming, todayilearned
Published: 2022-10-28 03:18:20

Asynchronous programming allows a program to do work while waiting for something else to complete. In this tutorial, we'll show you how to work with Future in Dart (also in <a href="https://bezkoder.com/tag/flutter/">Flutter</a>). At the end, you're gonna know:
<ul>
	<li>Introduction to <a href="https://bezkoder.com/tag/dart/">Dart</a> Future</li>
	<li>How to create Future, Future delayed and value methods</li>
	<li>Basic Future usage: then, catchError and callback</li>
	<li>Way to use Future async-await</li>
	<li>Future multiple await/then for chain of multiple asynchronous methods</li>
	<li>Equivalent of 'finally': Future whenComplete</li>
	<li>Future wait for multiple futures complete</li>
</ul>

This tutorial is originally from Bezkoder:
[https://www.bezkoder.com/dart-future/](https://www.bezkoder.com/dart-future/)

<h2>Dart Future overview</h2>
A <a href="https://api.dart.dev/stable/dart-async/Future-class.html">Future</a> represents a potential value (success), or error (fail), that will be available in the future. Generally we will need to work with a future value in following cases:
<ul>
	<li>getting data from a server</li>
	<li>querying data from a database</li>
	<li>reading a file</li>
	<li>doing a complicated computational work</li>
</ul>

```dart
Future<int> future = getFuture();
Future<Tutorial> tutorialsFut = getTutorialsFromDatabase(query);
Future<Data> dataFut = fetchDataFromServer(url);
Future<int> resultFut = computeBigData(value);
```

<h2>Dart Future then</h2>
We can use <code>then()</code> to indicate code that runs when the future completes.

For example, <code>fetchDataFromServer()</code> returns a <code>Future</code>.

```dart
Future<Data> future = fetchDataFromServer(url);
future.then((Data data) {
  print(data.values);
});
```

<h2>Dart Future callback</h2>
In the example above, we register a <code>callback</code> that handles the value of a Future result. How about an error? We're gonna use <code>catchError(callback)</code>.

For example:
```dart
Future<Data> future = fetchDataFromServer(url);
future.then((data) => handleData(data))
      .catchError((error) => handleError(error));
```

<h2>Dart async-await</h2>
The <code>async</code> and <code>await</code> keywords provide a declarative way to define asynchronous function (that returns a <code>Future</code>) and use its result. 

We must remember 2 basic conditions:
<ul>
	<li>Asynchronous function has <code>async</code> before the function body.</li>
	<li>The <code>await</code> keyword works only in <code>async</code> functions.</li>
</ul>

For example, we're gonna re-write the Future then above with async-await style.
```dart
main() async {
  Data data = await fetchDataFromServer(url);
  handleData(data);
}
```

Furthermore, then-catchError is equivalent to async-await like this:
```dart
main() async {
  try {
    Data data = await fetchDataFromServer(url);
    handleData(data);
  } catch (error) {
    handleError(error);
  }
}
```

Let's continue with some simple ways to create a <code>Future</code>.

<h2>Dart Future delayed</h2>
```dart
Future<T>.delayed(Duration duration, [computation()?])
```

<code>delayed()</code> method creates a <code>Future</code> that runs <code>computation</code> after the given duration has passed, and the future is completed with the result of the <code>computation</code>.

If the <code>duration</code> is <code>0</code> or less, it completes no sooner than in the next event-loop iteration, after all microtasks have run.

For example:
```dart
Future.delayed(Duration(seconds: 2), () => 'Delayed 2 seconds.')
      .then((result) => print(result));
```

async-await:
```dart
var result = await Future.delayed(Duration(seconds: 2), () => 'Delayed 2 seconds.');
print(result);
```

Output:
<pre><code>(after 2 seconds)
Delayed 2 seconds.
</code></pre>

<h2>Dart Future value</h2>
```dart
Future<T>.value(value)
```

The method <code>Future.value()</code> creates a Future completed with <code>value</code>.

For example:
```dart
Future.value("bezkoder.com")
      .then((result) => print(result));
```

async-await:
```dart
var result = await Future.value("bezkoder.com");
print(result);
```

Output:
<pre><code>bezkoder.com
</code></pre>

<h2>Dart Future error</h2>
<code>Future.error(Object error)</code> creates a future that completes with an <code>error</code>.

For example:
```dart
Future.error('> This is an error message!')
      .catchError((err) => print(err));
```

async-await:
```dart
try {
  await Future.error('> This is an error message!');
} catch (err) {
  print(err);
}
```

Output:
<pre><code>> This is an error message!
</code></pre>

<h2>Write asynchronous Function with Future</h2>
Now we create a asynchronous function that returns a <code>Future</code>. The function receives an input <code>int</code> number. If the input number is less than <code>0</code>, it completes with a Future error, or else, completes after given time and return the input number.

```dart
Future<int> doInSeconds(int sec) {
  print('> Processing with value=${sec}...');

  if (sec <= 0) {
    return Future.error('> input \'sec\' must be greater than 0');
  }

  return Future.delayed(Duration(seconds: sec), () {
    print('> Something done in ${sec} second(s).');
    return sec;
  });
}
```

Let's use <code>doInSeconds()</code> function.
```dart
doInSeconds(2).then((result) {
  print(result);
}).catchError((error) {
  print('> inside catchError');
  print(error);
});
```

Or:
```dart
try {
  var result = await doInSeconds(2);
  print(result);
} catch (error) {
  print(error);
}
```

Output:
```dart
> Processing with value=2...
(after 2 seconds)
> Something done in 2 second(s).
2
```

Check the catching Error:
```dart
try {
  var result = await doInSeconds(-1);
  print(result);
} catch (error) {
  print('> inside catchError');
  print(error);
}
```

Output:
<pre><code>> Processing with value=-1...
> inside catchError
> input 'sec' must be greater than 0
</code></pre>

<h2>Chain of multiple asynchronous methods in Dart</h2>
This is how we handle the case in that we need to call run multiple asynchronous functions in a certain order.

```dart
Future future = doInSeconds(1);
future
    .then((v1) => doInSeconds(v1 + 1))
    .then((v2) => doInSeconds(v2 + 1))
    .catchError((error) => print(error));
```

Output:
<pre><code>> Processing with value=1...
> Something done in 1 second(s).
> Processing with value=2...
> Something done in 2 second(s).
> Processing with value=3...
> Something done in 3 second(s).
</code></pre>

<ul>
	<li>If the callback inside <code>then()</code> returns a Future, <code>then()</code> returns a Future that will complete with the same result.</li>
	<li>If the callback returns a value of any other type, <code>then()</code> creates a new Future that completes with the value.</li>
</ul>

<h2>Dart multiple await</h2>
Let's run multiple asynchronous functions in chain using async-await:

```dart
try {
  final v1 = await doInSeconds(1);
  final v2 = await doInSeconds(v1 + 1);
  await doInSeconds(v2 + 1);
} catch (error) {
  print(error);
}
```

Output:
<pre><code>> Processing with value=1...
> Something done in 1 second(s).
> Processing with value=2...
> Something done in 2 second(s).
> Processing with value=3...
> Something done in 3 second(s).
</code></pre>

<h2>Dart Future whenComplete</h2>
We've known that <code>then-catchError</code> is equivalent to a <code>try-catch</code>, so <code>whenComplete</code> is for <code>finally</code>.

The callback inside <code>whenComplete()</code> is called after all, whether the result is with a value or with an error.

try-catch-finally:
```dart
try {
  final v1 = await doInSeconds(1);
  final v2 = await doInSeconds(v1 + 1);
  await doInSeconds(v2 + 1);
} catch (error) {
  print(error);
} finally {
  print("Done!");
}
```

equivalent:
```dart
Future future = doInSeconds(1);
future
    .then((v1) => doInSeconds(v1 + 1))
    .then((v2) => doInSeconds(v2 + 1))
    .catchError((error) => print(error))
    .whenComplete(() => print("Done!"));
```

Output:
<pre><code>> Processing with value=1...
> Something done in 1 second(s).
> Processing with value=2...
> Something done in 2 second(s).
> Processing with value=3...
> Something done in 3 second(s).
Done!
</code></pre>

Check another code that will cause an error.

```dart
Future future = doInSeconds(1);
future
    .then((v1) => doInSeconds(v1 - 1))
    .then((v2) => doInSeconds(v2 - 1))
    .catchError((error) => print(error))
    .whenComplete(() => print("Done!"));
```

Output:
<pre><code>> Processing with value=1...
> Something done in 1 second(s).
> Processing with value=0...
> input 'sec' must be greater than 0
Done!
</code></pre>

<h2>Future wait in Dart</h2>
If you need to run many asynchronous functions and wait for them all to complete before continuing something else, you can use static method: <code>Future.wait()</code> to manage multiple Futures:

```dart
var query = doInSeconds;
var compute = doInSeconds;
var work = doInSeconds;
await Future.wait([
  query(1),
  compute(6),
  work(3),
]);
print('Done!');
```

Output:
<pre><code>> Processing with value=1...
> Processing with value=6...
> Processing with value=3...
> Something done in 1 second(s).
> Something done in 3 second(s).
> Something done in 6 second(s).
Done!
</code></pre>

<h2>Conclusion</h2>
In this tutorial, we've learned overview of a Dart/Flutter Future, how to create a Future simply using delayed or value method, how to work with then-catchError-whenComplete or try-catch-finally with Future async-await, way to handle chain of multiple asynchronous methods or Future wait for multiple futures complete.

Happy learning! See you again!
<h2>Further Reading</h2>
<ul>
	<li><a href="https://api.dart.dev/stable/dart-async/Future-class.html">Future class</a></li>
	<li><a href="https://dart.dev/guides/libraries/futures-error-handling">Future Error Handling</a></li></li>
</ul>
- <a href="https://www.bezkoder.com/dart-flutter-constructors/">Dart/Flutter Constructors tutorial with examples</a>
- <a href="https://www.bezkoder.com/dart-string-methods-operators-examples/">Dart/Flutter String Methods & Operators tutorial with examples</a>
- <a href="https://www.bezkoder.com/dart-list/">Dart/Flutter List Tutorial with Examples</a>
- <a href="https://bezkoder.com/dart-map/">Dart/Flutter Map Tutorial with Examples</a>
- <a href="https://www.bezkoder.com/dart-sort-list-of-objects/">Dart/Flutter – Sort list of Objects</a>