# 18.异步编程之Future

### 代码执行顺序

下面一段代码的执行顺序是很明显的

```
int number = 1;

void main() {
  print('${DateTime.now()} start: $number');

  doSomeThing();

  print('${DateTime.now()} end: $number');
}

doSomeThing() {
  for(int i = 0; i < 1000000000; i++) {
    number += 1;
  }
  print('${DateTime.now()}  $number');
}
```

顺序输出没有什么问题

```
flutter: 2021-11-26 19:53:59.727819 start: 1
flutter: 2021-11-26 19:54:02.463404  1000000001
flutter: 2021-11-26 19:54:02.463815 end: 1000000001
```

### async

加上 `async` 呢？是不是就变成异步的了？

```
int number = 1;

void main() {
  print('${DateTime.now()} start: $number');

  doSomeThing();

  print('${DateTime.now()} end: $number');
}

doSomeThing() async {
  for(int i = 0; i < 1000000000; i++) {
    number += 1;
  }
  print('${DateTime.now()}  $number');
}
```

并没有什么变化，依然按顺序同步执行。

```
flutter: 2021-11-26 19:57:19.945126 start: 1
flutter: 2021-11-26 19:57:22.676219  1000000001
flutter: 2021-11-26 19:57:22.678135 end: 1000000001
```

### Future

在上文[16.第三方库导入与网络数据异步请求与展示](/wiki/flutter/16.-di-san-fang-ku-dao-ru-yu-wang-luo-shu-ju-yi-bu-qing-qiu-yu-zhan-shi.md)中我们的有用到 Future 进行异步网络请求。这里我们模拟网络请求，将耗时操作进行包装：

```
int number = 1;

void main() {
  print('${DateTime.now()} start: $number');

  doSomeThing();

  print('${DateTime.now()} end: $number');
}

doSomeThing() {
  Future( () {
    for(int i = 0; i < 1000000000; i++) {
      number += 1;
    }
    print('${DateTime.now()}  $number');
  });
}
```

通过打印我们发现这里的确是异步执行的：

```
flutter: 2021-11-26 20:01:22.301321 start: 1
flutter: 2021-11-26 20:01:22.306180 end: 1
flutter: 2021-11-26 20:01:25.041822  1000000001
```

#### Future是什么

通过查看源码我们能够发现。它是一个工厂构造函数。

```
  factory Future(FutureOr<T> computation()) {
    _Future<T> result = new _Future<T>();
    Timer.run(() {
      try {
        result._complete(computation());
      } catch (e, s) {
        _completeWithErrorCallback(result, e, s);
      }
    });
    return result;
  }
```

#### async - await

思考一下，下面代码的执行顺序会是什么样呢？

```
nt number = 1;

void main() {
  print('${DateTime.now()} start: $number');

  doSomeThing();

  print('${DateTime.now()} end: $number');
}

doSomeThing() async {
  await Future( () {
    for(int i = 0; i < 1000000000; i++) {
      number += 1;
    }
    print('${DateTime.now()}  $number');
  });
  print('doSomeThing结束');
}
```

这里进行一下简单的分析：

* 在 `doSomeThing` 内
  * `Future` 是异步执行的
  * 但 `Future` 加了 `await`，那么在当前作用域中，后面的代码就会被阻塞。
    * 即 `print('doSomeThing结束');` 这段代码会等待 `Future` 内的任务完成才执行。
* main 函数内
  * 三行代码执行是按顺序执行的，不会受 `doSomeThing` 内部的 await 的影响
* 按照预期输出应为：
  * start
  * end
  * `print('${DateTime.now()} $number');`
  * doSomeThing结束

执行验证✅

```
flutter: 2021-11-26 20:09:46.105049 start: 1
flutter: 2021-11-26 20:09:46.114976 end: 1
flutter: 2021-11-26 20:09:48.872681  1000000001
flutter: doSomeThing结束
```

> async 和 await 是成对出现的。你也可以试试只写 await，看看是什么效果。

#### then 与任务的返回值

对 `Future` 有所了解的话，知道通过 `then` 我们可以在任务完成的时候进行一些操作。下面对代码嫂做修改：

```
int number = 1;

void main() {
  print('${DateTime.now()} start: $number');

  doSomeThing();

  print('${DateTime.now()} end: $number');
}

doSomeThing() async {
  await Future( () {
    for(int i = 0; i < 1000000000; i++) {
      number += 1;
    }
    print('${DateTime.now()}  $number');
  }).then( (value) {
    print('then: ${DateTime.now()}  $value');
  });
  print('doSomeThing结束');
}
```

输出：

```
flutter: 2021-11-26 20:20:39.641708 start: 1
flutter: 2021-11-26 20:20:39.649521 end: 1
flutter: 2021-11-26 20:20:42.388725  1000000001
flutter: then: 2021-11-26 20:20:42.390922  null
flutter: doSomeThing结束
```

这里 `then` 回调里的 `value` 是空的，该怎样为 `value` 赋值呢？很简单，直接在 `Future` 的任务中 `return` 就可以了

这里再次修改代码：

```
int number = 1;

void main() {
  print('${DateTime.now()} start: $number');

  doSomeThing();

  print('${DateTime.now()} end: $number');
}

doSomeThing() async {
  await Future( () {
    for(int i = 0; i < 1000000000; i++) {
      number += 1;
    }
    return number;
  }).then( (value) {
    print('then: ${DateTime.now()}  $value');
  });
  print('doSomeThing结束');
}
```

输出验证✅

```
flutter: 2021-11-26 20:23:45.843172 start: 1
flutter: 2021-11-26 20:23:45.850300 end: 1
flutter: then: 2021-11-26 20:23:48.584267  1000000001
flutter: doSomeThing结束
```

符合预期。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ryukiedev.gitbook.io/wiki/flutter/18.-yi-bu-bian-cheng-zhi-future.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
