Before we get into Async and await, Dart is a single-threaded model, not an asynchronous operation with child threads. Async and await implementations of Async and await are only suitable for time-consuming operations of the wait type, such as interface requests, where time is spent waiting while the thread is doing other things. If the time-consuming operation is computationally intensive, it is not applicable and the calculation will block until the calculation is complete. Because from start to finish, it’s a single thread. Dart’s Event loop model is involved here: Event Loops

Let’s look at an example:

The code is simple: _startMethod indirectly calls a network request and returns a string of HTML.

import 'dart:io';
import 'package:http/http.dart' as http;

main() {
  _startMethod();
  print("C");
}


 Future _startMethod() async{
  print("A starts executing this method ~");
  print(await getHttp());
  print("A End of execution");
}

Future<String> getHttp() async {
  final result = await http.get('https://www.jianshu.com/');
  return "Requested data:" +  result.body.toString();
}
Copy the code

Execution result: While the interface waits, the rest of the main method code is executed and “C start” is printed before the interface returns data is printed. Asynchronous processing effect is achieved.

I/flutter (22228A starts executing this method ~ I/flutter (22228C start I/flutter (22228): Requested data: <! DOCTYPE HTML >........................... The returned HTML I/flutter (22228): A The execution is completeCopy the code

There are two layers of async and await combinations, so for the sake of understanding we will just look at the first layer of async and await methods. Regardless of the code in getHttp, just know that it initiates a request and returns the result of the request. This method takes time to wait.

According to official documents, the following points can be summarized:

1. awaitMust be inasyncMethod.

2.asyncIn the methodawaitThe previous code is immediately synchronized until it hitsawait.

3.awaitIs used to wait for the marked method (i.egetHttp) gets the return result.

Await getHttp()// This expression is the return String: "The requested data: "+ result.body.tostring () // Without await, getHttp () returns a Future, does not wait, executes the following code immediatelyCopy the code

When the code goes to await getHttp(), the getHttp code will execute (initiate the request, but have not yet received the result). The code after await will not execute until getHttp returns the result.

4. When the code executes toawait, one is returned immediatelyfuture.

That is, the _startMethod method will be returned with a future immediately after getHttp is executed. Then proceed with the rest of main, print(“C begins “); . When the result of the request is returned, the code behind “await” will resume execution and print the returned HTTP message and print(“A execution finished “), so the whole program ends. The whole process is similar to the non-blocking suspend of the Kotlin coroutine.

Let’s seegetHttpMethod, plus two prints

Future<String> getHttp() async {
  print("B starts executing this method ~");
  final result = await http.get('https://www.jianshu.com/');
  print("B get Http end ~");
  return "Requested data:" +  result.body.toString();
}
Copy the code

The result is as follows:

I/flutter (22228A starts executing this method ~ I/flutter (22228): B starts executing this method ~ I/flutter (22228C start I/flutter (22228): B get Http end ~ I/flutter (22228): Requested data: <! DOCTYPE HTML >... HTML I/flutter (22228): A The execution is completeCopy the code

In the same way, print(“B starts executing this method ~”) is executed, and http.get is executed while await is executed, and nothing after await is executed. And immediately returns a Future to the next level. Similar to a recursive idea, after the interface returns, the inner getHttp is restored first, and then the _startMethod is restored.

Expand a few questions to understandawaitRunning features:

Question 1: If inmainMethod add time-consuming operation:sleep(Duration(seconds: 10))What happens?

main() {
  _startMethod();
  print("C");
  sleep(Duration(seconds: 10));
}
Copy the code

The result is that after printing “C start “, it blocks for 10 seconds, and it takes 10 seconds for subsequent HTTP results to be printed. In the meantime, even though the interface has returned data, it does not immediately resume executing the code after await. Why? Dart’s EventLoop event model shows that the main method does not continue to fetch events from the EventLoop until the execution is complete. The interface’s future has a return value and simply sends an event to the EventLoop to queue up for processing. Since the thread is not idle at this time, it is performing a 10-second sleep and does not pull out the event execution. Until the main method is idle, the event is retrieved and the HTTP return is printed. Dart’s await is async and resumes execution of the await code only when the thread is idle.

Question 2: If removemainIn thesleep,http.getMethods forsleepWhat happens in 10 seconds?

Future<String> getHttp() async {
   print("B starts executing this method ~");
   await sleep(Duration(seconds: 10));
   print("B Sleep over ~");
   return "Requested data: XXXXXX"  ;
}
Copy the code

The result is as follows: wait 10 seconds after printing “B starts executing this method”. No additional code is executed during the wait.

I/flutter (22228A starts executing this method ~ I/flutter (22228): B Start executing this method ~// Wait 10 seconds
I/flutter (22228C start I/flutter (22228): B get Http end ~ I/flutter (22228): requested data: XXXXXX I/flutter (22228): A The execution is completeCopy the code

Here the sleep is blocking, which is computationally intensive, the entire thread is blocked, and the rest of the main method doesn’t execute until 10 seconds have elapsed.

Question 3: If you take out question 2awaitWhat about keywords?

Future<String> getHttp() async {
   print("B starts executing this method ~");
   sleep(Duration(seconds: 3));
   print("B Sleep over ~");
   return "Requested data: XXXXXX"  ;
}
Copy the code

The result is as follows: “C Start” and “B get Http end ~” change positions. Without await, the entire getHttp() code will be executed sequentially. That is, await changes the order in which code is executed, because execution to await immediately returns a future, and execution of the outer code continues while waiting.

I/flutter (22228A starts executing this method ~ I/flutter (22228): B Start executing this method ~// Wait 10 seconds
I/flutter (22228): B get Http end ~ I/flutter (22228C start I/flutter (22228): requested data: XXXXXX I/flutter (22228): A The execution is completeCopy the code

Key points:

  1. Asynchro of await in Dart is single-threaded asynchro, and upon execution to await, methods marked before and before await are executed immediately (such as initiating a request operation). Then immediately return a Future and continue executing the rest of the outer code. The code behind await will not be executed. The code behind await will resume execution only if the future returns the result. In this way, the effect is asynchronous.

  2. A set of async and await methods involves two futures. The method to the right of the await keyword is a future and the async method return value must also be a Future. After the future of the await token completes execution, the code following the await token continues. The future returned by the async method is not completed until the async method returns.

  3. If the method marked with await is of the wait type, the outer code can continue to run while await.

  4. If the method marked with await is computationally intensive, it will block here and wait until the computation is complete before running the outer code, thus not achieving the asynchronous effect.

  5. Await changes the execution order. Because the code behind await is already sent to Event Loops as an event. The remaining outer main methods are executed before the event is executed. Whether to execute main during or after a wait depends on points 3 and 4 above.

Finally, try this example again: Compute blocks as well as sleep, while the network request returns to continue running the outer layer of code while it waits.

Future<String> getHttp() async {
  print("B starts executing this method ~");
// final result = await http.get('https://www.jianshu.com/');
   await compute();
  print("B get Http end ~");
  return "Requested data:";
}

Future<String> compute() async {
  int b = 0;
  for(int i= 0 ; i < 1000000000 ; i ++){
    b++;
  }
  return "Compute data:";
}
Copy the code

Reference:

  • Dart event model
  • Future
  • Async and await
  • The Dart asynchronous