Future in dart: When to use async, await, and then
Asynchronous programming in dart

I build apps, internal tools, and sketch stuff on my iPad. Into side projects, and occasionally sharing thoughts here.
Search for a command to run...
Asynchronous programming in dart

I build apps, internal tools, and sketch stuff on my iPad. Into side projects, and occasionally sharing thoughts here.
Thank you. 😊
Experiences, lessons, and technical deep dives from building mobile applications. Topics span Flutter, Dart, mobile architecture, application state, performance, and production software development.
When working on frontend applications, a common use case is "Updating the screen's UI dynamically". setState is one of the ways to accomplish this in flutter. Tech Terms These are some common terms us
I read Design Patterns Explained 2nd Edition a few months ago. I thought I'd finally write about it and some of the lessons I took away from it.I was reading the final chapters while starting Offline

Human Learning ML — Devlog #1

I used to think of tests as just a final check to confirm whether a feature worked. That perspective shifted a few years ago when I had shipped a feature, and later a teammate made changes that uninte

A sudden AI interest in my company has left me avoiding it as much as possible. I’ve been using Copilot for 3 years now and have been very happy with it. When ChatGPT launched, I quickly created an ac

Introduction Hey there! I'm trying out something new today. This is not a tutorial blog but more of a personal development blog.It has no conclusion or takeaway if that's what you're looking for. This

There are multiple ways to implement asynchronous logic in dart. Dart provides three keywords for this: async, await, and then.
In this blog, we'll learn how and when to use them according to our needs.
Asynchronous programming refers to a block of code that runs in parallel with other blocks of code. As a result, we can do several things at the same time.
For example, say we have an API request that fetches a list of recipes. This network call might take some time. During this fetching, we have a text field where a user can type into.
Our application is interacting with the user as well as fetching recipes simultaneously.
Another way to think about this is, doing some background tasks separately without disrupting the main task flow.
Dart gives us two ways to implement asynchronous logic:
In this blog, we'll discuss Future.Future class has various constructors that we can use. There are certain keywords that we need to implement when using them. The keywords are: async, await, and then.
thenthen works on the concept of callbacks. The callback is exactly what it says it is. Calling back (executing) a block of code sometime later.
Let's say we are fetching a list of recipes. This returns a Future.
After the Future is completed (we've fetched the recipes), we want to display a message to the user.
During this fetching, we don't want to stick there but continue to execute our next block of code.
Let's look at the following code. For simplicity, we'll use print statements.
You can run the code sample below in dartpad. Just copy-paste the code in dartpad and run it.
void main() {
print('start fetching recipes');
Future.delayed(Duration(seconds: 1), () {
print('recipes fetched');
}).then((_) {
print('after fetching recipes');
});
String computation = 'a random computation';
print(computation);
}
Let's understand the code.
In line 4, we are fetching our recipes.
Here, we've used the
Future.delayedconstructor for demo purposes. Using this, we can specify the time we want to wait for (here we are waiting for 1 second).
Refer here, if you want to know more about this function.
In lines 6-8, we are giving a callback (a block of code) that is supposed to run when the recipes are fetched (or Future is completed).
The code after line 8 should not wait for the recipes to be fetched but continue to execute.
Output:
start fetching recipes
a random computation
recipes fetched
after fetching recipes
Analysing the output:
The first console print statement is start fetching recipes as expected.
The second console print statement is a random computation. This is the desired result. The Future takes time to complete and the rest of the code (below line 8) does not wait for it to complete but executes.
After a while, recipes fetched and after fetching recipes executes which were the callbacks for the Future.
So, then fits here perfectly.
Now let's see another use case.
After the Future is completed (we've fetched the recipes), we want to display a message to the user.
We want to wait for the recipes to be fetched and not execute the lines below 8.
The easiest way would be to put all the code inside the then block.
Run the code in dartpad.
void main() {
print('start fetching recipes');
Future.delayed(Duration(seconds: 1), () {
print('recipes fetched');
}).then((_) {
print('after fetching recipes');
String computation = 'a random computation';
print(computation);
});
}
Output:
start fetching recipes
recipes fetched
after fetching recipes
a random computation
We've just added everything under the then block. Now, the a random computation is executed after the recipes are fetched.
There's a better way to implement this use case.
Since we want to wait for the recipes to be fetched and not execute the code below, we could use simpler syntax.
And that's what async and await are. An alternative syntax to implement asynchronous logic.
async-awaitLet's implement our second use case again. Run the code in dartpad.
void main() async {
print('start fetching recipes');
await Future.delayed(Duration(seconds: 1), () {
print('recipes fetched');
});
print('after fetching recipes');
String computation = 'a random computation';
print(computation);
}
Output:
start fetching recipes
recipes fetched
after fetching recipes
a random computation
This time, we've not used any callbacks explicitly like the then block. Instead, we've added async in line 1 and await in line 4.
async keyword tells dart that this function might use asynchronous logic. So void main has the async keyword.
await keyword tells dart that the following statement will return a Future. The Future should be completed and then the code below will be executed.
Let's look at some more examples.
As seen above, we can have multiple implementations for the same logic. Let's look at some code samples and try to simplify them.
void main() async {
await Future.delayed(Duration(seconds: 1), () {
print('inside delayed');
}).then((_) {
print('inside then');
});
print('after delayed');
}
The then block is redundant here. Since we're awaiting the Future, the then callback can be implemented like a normal code of block.
Simplified:
void main() async {
await Future.delayed(Duration(seconds: 1), () {
print('inside delayed');
});
print('inside then');
print('after delayed');
}
void main() {
Future.delayed(Duration(seconds: 1), () {
print('inside delayed 1');
}).then((_) {
print('inside then 1');
Future.delayed(Duration(seconds: 1), () {
print('inside delayed 2');
}).then((_) {
print('inside then 2');
});
});
print('after delayed');
}
There is a nesting of then blocks here. We can use async, await syntax inside a then block also.
Simplified:
void main() {
Future.delayed(Duration(seconds: 1), () {
print('inside delayed 1');
}).then((_) async {
print('inside then 1');
await Future.delayed(Duration(seconds: 1), () {
print('inside delayed 2');
});
print('inside then 2');
});
print('after delayed');
}
I hope the examples helped in understanding the various syntaxes.
And that's it for asynchronous programming in dart using Future.
We can use then syntax or async-await syntax or both to implement asynchronous logic.
Any syntax can be used to achieve our desired result. But we should also focus on code-readability.
For further reading, you can refer to dart official docs.
Thank you for reading this article. If you enjoyed it, consider sharing it with other people.
If you find any mistakes, please let me know.
Feel free to share your opinions below.