“This is the 8th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021”

The Future of asynchronous

The Future was used in the network request above, so what is this? Fluture is asynchronous code in the main thread

  1. What is the following order of printing:
void main() {
  testFuture();
  print('A');
}

void testFuture() async {
  Future(() {
    print('C');
  });
  print('B');
}
Copy the code

  1. joinawaitWhat is the order of printing after that?
void main() {
  testFuture();
  print('A');
}

void testFuture() async {
  await Future(() {
    print('C');
  }).then((value) => print('D'));
  print('B');
}
Copy the code

Tests have found that code blocks decorated with the Future execute asynchronously and do not block the current thread. If you want to wait until the asynchronous task has completed, you need to prefix the Future with an await.

  1. multipleFuturePrint order in parallel:
void main() {
  testFuture();
  print('A');
}

void testFuture() async {
  Future(() {
    return 'task 1';
  }).then((value) => print('$valueEnd of execution));

  Future(() {
    return 'task 2';
  }).then((value) => print('$valueEnd of execution));

  Future(() {
    return 'task 3';
  }).then((value) => print('$valueEnd of execution));

  Future(() {
    return 'task 4';
  }).then((value) => print('$valueEnd of execution));
  
  print('Task added completed');
}
Copy the code

After adjusting the order or adding multiple tests such as sleep to one of the tasks, the order in which multiple futures are found to be executed in parallel is the order in which they are added.

  1. There is a dependencyFuturePrint order:
void testFuture() async {
  Future(() {
    return 'task 1';
  }).then((value) {
    print('$valueThe end of the ');
    return '$valueTask 2 ';
  }).then((value) {
    print('$valueThe end of the ');
    return '$valueTask 3 ';
  }).then((value) {
    print('$valueThe end of the ');
    return '$valueTask 4 ';
  });
}
Copy the code

  1. multipleFutureOperation after completion:
void testFuture() async {
  Future.wait([
    Future(() {
      return 'task 1';
    }),
    Future(() {
      return 'task 2';
    }),
    Future(() {
      return 'task 3';
    }),
    Future(() {
      return 'task 4';
    }),
  ]).then((value) => print('$value')); // The order of execution in wait is also the order of addition
}
Copy the code

  1. scheduleMicrotaskYou can cut in lineFutureIn front of the task
void testFuture() async {
  Future.wait([
    Future(() {
      return 'task 1';
    }),
    Future(() {
      return 'task 2';
    }),
    Future(() {
      return 'task 3';
    }),
    Future(() {
      return 'task 4';
    }),
  ]).then((value) => print('$value'));

  scheduleMicrotask(() {
    print('scheduleMicrotask');
  });
}
Copy the code

Dart has only two types of queues: event queues and microtask queues, which always take precedence over event queues.

Below is the official image:

  1. In what order should the following be printed?
void testFuture() async {
  Future x = Future(() => print('A'));
  Future(() => print('B'));
  scheduleMicrotask(() {
    print('C');
  });
  x.then((value) => print('D'));
  print('E');
}

Copy the code

It must be E for the main thread first, then C for the microtask, and the remaining two futures are executed in the order they are added, starting with A and D and ending with B

  1. FlutureThe execution sequence of nested microtasks in:
void testFuture() async {
  Future(() => print('A')).then((value) {
    scheduleMicrotask(() {
      print('D');
    });
  }).then((value) => print('F'));
  Future(() => print('B'));
  scheduleMicrotask(() {
    print('C');
  });
  print('E');
}
Copy the code

The code after then can be interpreted as being thrown to the microtask queue for execution.

Add: use chain calls when using Flutter, make sure to call.catchError at the end to catch exceptions

getData() async {
  print('Here we go.');
  await Future(() {
    for (int i = 0; i < 100; i++) {}
    return 'End of loop';
  })
      .then((value) => print('$value'))
      .whenComplete(() => print('Done'))
      .catchError((e) => print(e.toString()));
  print('Code after await');
}
Copy the code

Multithreading in Dart

The Isolate in Dart is more like a process, with its own memory space. This means that the data between each process is independent and there is no space grab, so the concept of locking is not needed.

void main() {
  IsolateDemo();
}

void IsolateDemo() {
  print('1');
  Isolate.spawn(func, 3);
  Isolate.spawn(func, 4);
  Isolate.spawn(func, 5);
  Isolate.spawn(func, 6);
  Isolate.spawn(func, 7);
  Isolate.spawn(func, 8);
  Isolate.spawn(func, 9);
  sleep(Duration(seconds: 3));
  print('2');
}
Copy the code

The above said that there is no same block of memory problem, let’s also verify, in the code below, I inIsolateIf the value of a is changed, then the last printed a=?

int a = 100;
void IsolateDemo() {
  print('1');
  Isolate.spawn(func, 3);
  Isolate.spawn(func, 4);
  Isolate.spawn(func, 5);
  Isolate.spawn(func, 6);
  Isolate.spawn(func, 7);
  Isolate.spawn(func, 8);
  Isolate.spawn(func, 9);
  sleep(Duration(seconds: 3));
  print('2');
  print('a = $a');
}

func(int count) {
  print('$count');
  a = count;
}
Copy the code

It turns out that in the end, a is equal to 100IsolateThe changes in the.

ReceivePort & Isolate

void IsolateDemo() {
  print('1');
  ReceivePort port = ReceivePort();
  Isolate.spawn(func, port.sendPort);
  port.listen((message) {
    print('message=$message');
  });
  sleep(Duration(seconds: 3));
  print('2');
}

func(SendPort port) {
  port.send(10);
}
Copy the code

There is one thing that needs to be fixed in the code above: note that you need to manually shut down ports and destroy the Isolate

void IsolateDemo() async {
  print('1');
  ReceivePort port = ReceivePort();
  Isolate iso = await Isolate.spawn(func, port.sendPort);
  port.listen((message) {
    print('message=$message');
    port.close();
    iso.kill();
  });
  sleep(Duration(seconds: 3));
  print('2');
}
Copy the code

compute

Similar to Isolate, it is a further wrapper on Isolate. Compute does not require a manual kill

void main() {
  Comouterdemo();
}

void Comouterdemo() {
  print('1');
  compute(func1, 10);
  sleep(Duration(seconds: 3));
  print('2');
}

func1(int num) {
  print('$num');
}
Copy the code

Use asynchrony with await

void main() {
  Comouterdemo();
}

void Comouterdemo() async {
  print('1');
  int result = await compute(func1, 10);
  sleep(Duration(seconds: 3));
  print('result=$result');
  print('2');
}

int func1(int num) {
  print('$num');
  return num;
}
Copy the code

A little knowledge

  • In the case of imports, the AS keyword aliases the library to prevent class and method name conflictsimport 'package:http/http.dart' as http;
  • Import library, the default is to import the entire file, if you need to specify two keywords.show: Executes the content to be imported.Hide:Content to hide
  • pubspec.yamlIn thepublish_to: Specify where to publish to, default is topub.devTo go inside
  • pubspec.yamlIn theversion: Indicates the version number of the current project
  • pubspec.yamlDart version inEnvironment: the SDK: "> = 2.12.0 < 3.0.0"
  • pubspec.yamlIn thedev_dependenciesReleases that the development environment depends on are packaged without this
  • pubspec.yamlIn thedependencies: third-party library import location.Dio: ^ 4.0.1The big version of the invariant interval is equal to> = 4.0.1 < 5.0.0; Dio: 4.0.1Specify version 4.0.1;dio:anyAny version