When learning the Dart asynchronous programming, you need to sort out the relevant knowledge system involved in asynchronous programming. We can understand the content involved in asynchronous programming one by one according to the following questions:

  • Why do you need asynchronous programming?
  • What is the underlying mechanism of asynchronous programming?
  • How to do asynchronous programming in Dart?

[TOC]

isolate:

Dart is a single “threaded” language:

The Dart code runs in the context of an ISOLATE that has all the memory required for the Dart code. While the Dart code is executing, no other code in the same ISOLATE is running. More colloquially, Dart executes one operation at a time, which means that as long as an operation is executing, it is not interrupted by any other Dart code. This leads to the following questions:

1. If Dart code is taking time or waiting for I/O, the program will freeze.

2. If different Dart codes need to be run at the same time, these codes need to be executed in different ISOLATE environments;

3. How to write asynchronous code in Dart to perform asynchronous operations? (Asynchronous operations mean that while your program is waiting for other operations to complete, you can let other parts of your program complete first.)

Let’s start with the code:

main() {
  fallInLove();/ / to fall in love
  House newHourse = buyHouse();// Buy a house (time-consuming and laborious operation)
  livingHouse(newHourse);// Live in a new house after buying oneMary ();/ / to get married
  haveChild();/ / Eva
}
Copy the code

As shown above, in this case, only after the first statement is executed can the following statements be executed sequentially;

Most people live in three things: buy a house, get married and have a baby!

These three big things, if you use the Dart language:

If you’re in sync, and you don’t have a mine, and you don’t have six wallets for a down payment, you freeze your life — you wait until you buy a house, then you get married, and then you have a baby;

What operation can realize marry first, regenerate baby, buy a house again? The answer is yes: if buy a house (buyHouse()) in the asynchronous operation, this time you have to give your mother-in-law and wife a promise: later money to buy a house! Get married and have a baby now! We’ll talk about the details later, but here’s the idea;

event loop:

When the Flutter or Dart application is run, an ISOLATE is created and launched. When the ISOLATE is created, Dart does three things:

1. Initialize two first-in, first-out (FIFO) queues: one called MicroTask queue and the other called Event queue.

2. Run the main() method and go to 3

3. Start the Event Loop

4, start processing the elements in the two queues (the two queues are executed in order, see later)

In other words, each ISOLATE has only one Event Loop and two queues (MicroTask Queue and Event Queue). The Event Loop drives the execution mode and order of the code based on the contents of the MicroTask queue and the Event queue.

So here’s the question:

1. What is an Event Loop? What’s it for?

2. What are the MicroTask queue and Event queue respectively? What’s the use?

3. What’s the difference between the two?

An Event Loop is an infinite Loop that wakes up periodically: it searches MicroTask and Event queues to see if any tasks need to be run. If the tasks in the queue exist, the Event Loop puts them on the run stack for execution if and only if the CPU is idle.

MicroTask Queues are used for very short operations that need to be run asynchronously. Consider the following scenario: You want to complete some tasks later but before the next Event Queue executes; The dart: Async library scheduleMicrotask method is used.

The Event Queue contains all external events:

  • I/O,
  • Gestures,
  • Mouse event,
  • Drawing event,
  • The timer,
  • Message between isolates
  • Future

Each time an external Event is triggered, the corresponding code to be executed is added to the Event Queue. When there is no content in the MicroTask Queue, the Event Loop will fetch the first item from the Event Queue for processing. It is important to note that futures are also added to the Event queue;

When the main() method completes, the Event loop begins its work,

1. First fetch and execute all contents from the MicroTask queue in a first-in, first-out manner;

2. Fetch and process the first item from the Event queue.

3, repeat the above steps until there is nothing to execute on either queue

To sum up, it can be represented by the following simplified diagram:

Future:

A Future is usually a task that runs asynchronously and will be completed at some point in the Future. Completion can be defined as success or failure. On success, the result of the execution of the task is returned (note: the result is an object whose Future< T> returns the generic T), and on failure, an error is returned.

When instantiating a Future:

  • An instance of the Future is created and recorded in an internal array managed by Dart;
  • Code that needs to be executed by this Future is pushed directly to the Event queue;
  • A Future instance returns an unfinished Future object;
  • If there is any other code after the Future statement (other than the code contained in the Future), the next synchronization code continues;
  • After the Future is finished, code in the **then() and catchError () ** methods will be executed;

import 'dart:async';

void main() {
  fallInLove(); // Fall in love;
  handleHouse(); // Buying a house and moving in (time-consuming and expensive operation)
  marry(); / / to get married
  haveChild(); / / Eva
}

/// carry out operations such as buying a house and moving into a livingHouse
void handleHouse() {
  Future<House> house = buyHouse();
  house.then((_) {
    livingHouse();
  });
}

class House {}

Future<House> buyHouse() {
  Future<House> result = Future(() {
    print('buyHouse');
  });
  return result;
}

void livingHouse() {
  print('livingHouse');
}

void marry() {
  print('marry');
}

void haveChild() {
  print('haveChild');
}

void fallInLove() {
  print('fall in love');
}

Copy the code

Let’s analyze the execution order of the above code:

  1. frommain()Method to start executing the synchronization codefallInLove();
  2. performhandleHouse()Method, will the Future(){print('buyHouse'); }Join the Event queue;
  3. performmarry()Methods;
  4. performhaveChild()Methods;
  5. By the time I get to this point,main()The Event Loop starts to process the elements in the two queues, as in the previous analysis. At this time, the MicroTask queue is checked to see if there is any task to be processed. If there is no task, the first task in the Event queue is retrieved and executed(){print('buyHouse'); }The code block;
  6. When the above steps are complete, start the executionthen()The methods inlivingHouse(); ;

So the code should look something like this:

fall in love marry haveChild buyHouse livingHouse

async/await:

In the Future section above, we primarily use the Future API for asynchronous operations. Dart also provides a pair of keywords async/await for this purpose. With these two keywords, we can write asynchronous code just as we write synchronous code without using the Future’s API (then());

There are several caveat to using the async/await keyword:

  • A method declared with the async keyword that needs to return a Future object: Future< T> if a value is available; Future< void> if no value is available;
  • Await keyword can only be found in methods marked async;
  • The expression followed by the await keyword is usually a Future object. If not, the system will automatically wrap it as a Future object;
  • Await expressions cause the statement following the expression to suspend execution (in async methods) until the returned Future object is available;
  • Instead of using the **catchError()** method in the Future API, we can package await expressions in try/catch for error capture and subsequent processing.

As follows: We just need to change handleHouse() a little:

  1. Precede the body of the method with the async keyword
  2. willhandleHouse()Change the return type of method to Future< void>
  3. Add await keyword flag before operation methods that require time consuming
Future<void> handleHouse() async {await buyHouse(); livingHouse(); }Copy the code

The output after running the code is consistent with using the Future API;

conclusion

This article mainly involves the concepts of ISOLATE, Event loop, Future and async/await. Understanding these contents can help us to write and read the relevant code of asynchronous programming better.

Refer to the link

Dart. Dev /tutorials/l…

Dart. dev/guides/lang…

Dart. dev/articles/ar…