preface

Dart has no concept of processes and threads. All Dart code runs on ISOLATE. So what exactly is isolate? Articles in this series will discuss this in detail. This article discusses event loops and the order in which the Dart code runs.

0x00 Synchronous code and asynchronous code

We categorized Dart code into synchronous and asynchronous code; When we were writing the Dart code, there were only two types of code,

  • Synchronous code: lines of code written down
  • Asynchronous code: code decorated with Future, etc

The two types of code are different:

1. Different running sequences

Synchronous and asynchronous code run in a different order:

Run synchronous code first, then asynchronous codeCopy the code

That is, even if I write asynchronous code at the front and synchronous code at the back, sorry, I run the synchronous code at the back, and then I run the asynchronous code at the front after all the synchronous code runs.

2. Different operating mechanisms

Asynchronous code is run in an Event loop, which is a very important concept. It can be understood as the Looper mechanism in Android. It is an endless loop, and the event loop constantly takes events from the event queue and runs them.

0x01 Event Loop architecture

Here is a general diagram of the Event loop:

After understanding this, look at the detailed operation diagram of the Event loop:

From here, you can see that after starting the app:

  1. Check to see if the MicroTask Queue is empty. If not, run MicroTask first
  2. After a microtask is finished, the Event Queue 3 will be run only after the MicroTask queue is empty. After the Evnet Queue pulls out an Event Task and runs it, it goes to the first step to run the MicroTask

There are two additional nouns: MicroTask and Event, which represent two different asynchronous tasks

And it can be seen that:

  • If you want the task to be executed as quickly as possibleMicroTask

1. MicroTask

Dart: Async dart: Async dart: Async dart:async dart:async dart:async

// Adds a task to the MicroTask queue.scheduleMicroTask ((){//... code goes here... });Copy the code

Or:

new Future.microtask((){ // ... code goes here... });Copy the code

2.Event

Event is an asynchronous method that Future decorates.

// Adds a task to the Event queue. new Future(() { // ... code goes here... });Copy the code

0x02

It is not easy to understand purely theoretical knowledge, let’s go directly to the code, tell an example, look at the following code, may I ask what is the printing order?

import 'dart:async';
void main() {
  print('main #1 of 2');
  scheduleMicrotask(() => print('microtask #1 of 3'));

  new Future.delayed(new Duration(seconds:1),
      () => print('future #1 (delayed)'));

  new Future(() => print('future #2 of 4'))
      .then((_) => print('future #2a'))
      .then((_) {
        print('future #2b');
        scheduleMicrotask(() => print('microtask #0 (from future #2b)'));
      })
      .then((_) => print('future #2c'));

  scheduleMicrotask(() => print('microtask #2 of 3'));

  new Future(() => print('future #3 of 4'))
      .then((_) => new Future(
                   () => print('future #3a (a new future)')))
      .then((_) => print('future #3b'));

  new Future(() => print('future #4 of 4'))
  .then((_){
    new Future(() => print('future #4a'));
  })
  .then((_) => print('future #4b'));
  scheduleMicrotask(() => print('microtask #3 of 3'));
  print('main #2 of 2');
}
Copy the code
  1. Run the synchronization code first

    So it is:

    main #1 of 2
    main #2 of 2
    Copy the code
  2. Next up is asynchronous code

    Dart Event Loop checks whether there are any tasks in the MicroTask queue. If there are any, run the MicroTask. After the MicroTask is finished, run the Event Task in the Event Queue. Run the MicroTask Queue, and then run the Event Queue.

  3. microtask queue

    Here it is:

    microtask #1 of 3
    microtask #2 of 3
    Copy the code
  4. Event Queue Event queue There are special cases to consider:

    • Future.delayed

      Dart does not delay the execution of the task until the delay time expires, so if there is a time-consuming task ahead, your delayed task may not run on time

    • Future.then

      Tasks in future. then will not be added to the event queue, but will drop immediately after the current Future is executed. Therefore, if you want to ensure the execution order of asynchronous tasks, you must use THEN

    • scheduleMicrotask

    After an Event Task is finished, it checks the Micro Queue to see if there are any Micro Tasks that can be executed. If not, the next Event Task is executed

    Here it is:  ``` future #2 of 4 future #2a future #2b future #2c microtask #0 (from future #2b) future #3 of 4 future #4 of 4 future  #4b future #3a (a new future) future #3b future #4a future #1 (delayed) ```Copy the code

Future #4 of 4 (a new future) The task Future #3a (a new future) will be added to the end of the event queue because future #3 of 4 then creates a new future: Future #3a (a new future).

The end result:

main #1 of 2
main #2 of 2
microtask #1 of 3
microtask #2 of 3
microtask #3 of 3
future #2 of 4
future #2a
future #2b
future #2c
microtask #0 (from future #2b)
future #3 of 4
future #4 of 4
future #4b
future #3a (a new future)
future #3b
future #4a
future #1 (delayed)
Copy the code

Refer to the article

Webdev.dartlang.org/articles/pe…