Future核心原理深度解析
从Future状态管理到then链式调用再到错误处理,全面拆解Dart异步编程的核心原理与事件循环机制
一句话概括
Future是Dart中表示异步计算结果的占位符对象,通过状态机(未完成→已完成)驱动then链式调用,在单线程事件循环模型上实现了优雅的异步编程范式。
背景与意义
异步编程模型在Dart中的特殊位置
不同于JavaScript(天生事件驱动)或Java(线程模型),Dart的异步模型是单线程 + 事件循环 + Isolate并发:
1
2
3
4
JavaScript: 单线程事件循环(无隔离区)
Java: 多线程 + 共享内存
Dart: 单线程事件循环 + Isolate(独立内存)
Python: GIL + 协程(asyncio)
Dart的选择意味着:
- 不需要锁(单线程内无竞态)
- 不需要担心共享内存并发bug
- 但必须正确处理异步操作(否则UI会卡住)
为什么理解Future的底层原理很重要?
以一个常见的Flutter Bug为例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 新手常见错误
Future<void> loadData() async {
showLoading(); // 显示加载指示器
// "并行"请求两个API
final user = await fetchUser(); // 先等3秒
final posts = await fetchPosts(); // 再等2秒 —— 总共5秒!
hideLoading();
showData(user, posts);
}
// 实际需要并行请求:
Future<void> loadDataFixed() async {
showLoading();
// 同时发起两个请求,等待所有完成
final results = await Future.wait([
fetchUser(),
fetchPosts(),
]); // 并行执行——总共只需3秒!
hideLoading();
showData(results[0], results[1]);
}
如果不理解Future的创建时机和执行流程,就很难写出高效的异步代码。这个例子中,await 会阻塞后续代码的执行,但不会阻塞UI线程——理解这个”阻塞但又不阻塞”的微妙区别,正是Future原理的核心。
概念与定义
Future的核心概念
| 概念 | 定义 | 类比(餐厅点餐) |
|---|---|---|
| **Future | 表示稍后可用(或出错)的T类型值 | 点餐时拿到的小票 |
| 状态: uncompleted | 异步操作尚未完成 | 后厨还在做菜 |
| 状态: completed | 异步操作已完成,携带结果或错误 | 菜已上桌 |
| then() | 在Future完成后注册回调 | 让服务员上菜时通知你 |
| catchError() | 处理Future中的错误 | 菜做砸了,换菜或免单 |
| await | 语法糖:暂停当前函数直到Future完成 | 你坐着等,不干别的事 |
| Completer | 手动控制Future的完成 | 自己”手动”通知菜好了 |
Future的生命周期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
创建Future
│
▼
┌────────────────┐
│ Uncompleted │ ← 异步操作尚未开始或正在进行
│ (未完成) │
└───────┬────────┘
│
├── 异步操作成功 ──→ ┌──────────┐
│ │ Completed │ ← 携带value
│ │ (完成-值) │
│ └──────────┘
│
└── 异步操作失败 ──→ ┌──────────┐
│ Completed │ ← 携带error
│ (完成-错误)│
└──────────┘
最小示例:Future的完整生命周期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// future_lifecycle.dart
import 'dart:async';
void main() {
print('=== Future生命周期演示 ===\n');
// 1. 创建Future
print('1️⃣ 创建Future');
final future = Future<String>(() {
print(' 3️⃣ Future体开始执行(同步部分)');
// 模拟异步操作
return _heavyComputation();
});
print(' 2️⃣ Future已创建,程序继续执行');
// 2. 注册回调
print('\n2️⃣ 注册then回调');
future.then((value) {
print(' 5️⃣ then回调收到值: $value');
return '处理后的: $value';
}).then((processed) {
print(' 6️⃣ 链式then: $processed');
}).catchError((error) {
print(' ⚠️ 捕获错误: $error');
}).whenComplete(() {
print(' 7️⃣ whenComplete: 无论成功失败都会执行');
});
// 3. 主线程继续
print('\n3️⃣ 主线程继续执行其他代码');
for (int i = 0; i < 3; i++) {
print(' 主线程工作: $i');
}
print('\n4️⃣ main函数结束(但事件循环还在运行)');
}
Future<String> _heavyComputation() async {
print(' 🔄 计算开始...');
// 模拟耗时操作
await Future.delayed(Duration(milliseconds: 500));
print(' 🔄 计算完成');
return '计算结果: 42';
}
输出时序分析:
1
2
3
4
5
6
7
8
9
10
11
12
创建Future
Future已创建,程序继续执行(Future体还未执行)
注册then回调
主线程继续执行其他代码
main函数结束
Future体开始执行(同步部分)
→ 如果Future体中有await,会先返回
计算中...
计算完成
then回调收到值
链式then
whenComplete
核心知识点拆解
1. Future的创建方式
Dart中创建Future有6种方式,各有用途:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import 'dart:async';
import 'dart:io';
void main() {
// ---- 方式1: Future() 构造函数 ----
// 将同步函数调度到事件队列中异步执行
Future(() {
print('方式1: 在事件队列中执行');
return 42;
});
// ---- 方式2: Future.value() ----
// 创建一个已经完成的Future(微任务中执行)
Future.value('立即完成')
.then((v) => print('方式2: $v'));
// 等价于 Future(() => '立即完成') 但更高效
// ---- 方式3: Future.error() ----
// 创建一个已完成(错误状态)的Future
Future.error(Exception('出错了'))
.catchError((e) => print('方式3: $e'));
// ---- 方式4: Future.delayed() ----
// 延迟指定时间后完成
print('方式4: 开始');
Future.delayed(Duration(seconds: 1), () {
print('方式4: 1秒后执行');
return '延迟结果';
});
// ---- 方式5: Future.sync() ----
// 立即同步执行函数体(但在微任务中触发then回调)
Future.sync(() {
print('方式5: 同步执行');
return '同步值';
}).then((v) => print('方式5 then: $v'));
// ---- 方式6: Completer ----
// 手动控制Future何时完成
final completer = Completer<String>();
completer.future.then((v) => print('方式6: $v'));
// 在某个时刻手动完成
Future.delayed(Duration(milliseconds: 500), () {
completer.complete('手动完成的Future');
});
}
2. then链式调用
then 是Future的核心API,它返回一个新的Future,实现链式调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void main() {
// 链式调用的本质:then返回新Future
Future<String> step1 = Future.value('步骤1');
final chain = step1.then((value) {
print('收到: $value');
return '步骤2的结果'; // 返回新值
}).then((value) {
print('收到: $value');
return 42; // 可以改变类型:Future<String> → Future<int>
}).then((value) {
print('最终值: $value (类型: ${value.runtimeType})');
});
// chain 的类型是 Future<void>
// then回调可以返回三种东西之一:
/*
then((value) {
// 1. 普通值 → 包装为 Future<T>
return someValue;
// 2. Future<T> → 扁平化(不会变成Future<Future<T>>)
return Future.value(otherValue);
// 3. 不返回 → 返回 Future<void>
print('副作用');
})
*/
}
返回Future时的扁平化(Flattening):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void main() {
// 没有扁平化的话会怎样?
Future<String> outer = Future.value('外层');
outer.then((value) {
// 如果then直接返回 Future<String>
return _fetchData(value); // 返回Future<String>
}).then((result) {
// 如果没有扁平化,result 会是 Future<String>
// 但实际Dart会扁平化,result 是 String
print('收到: $result'); // 直接拿到String
});
}
Future<String> _fetchData(String param) async {
await Future.delayed(Duration(milliseconds: 100));
return '$param → 处理结果';
}
3. await 语法糖——then的等价转换
await 关键字是then的语法糖,但不完全等价:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 方式A: then 链
Future<String> getDataA() {
return fetchUser().then((user) {
return fetchPosts(user.id);
}).then((posts) {
return posts.first.title;
});
}
// 方式B: async/await
Future<String> getDataB() async {
final user = await fetchUser();
final posts = await fetchPosts(user.id);
return posts.first.title;
}
// 两者在语义上等价,但await版本:
// 1. 更易读——没有嵌套回调
// 2. 错误处理更直观——try/catch
// 3. 条件分支更自然——if/for/while
await的底层编译转换(简化):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 源码
Future<String> example() async {
final a = await fetchA();
final b = await fetchB(a);
return b;
}
// 编译器生成的近似代码
Future<String> example() {
final completer = Completer<String>();
fetchA().then((a) {
fetchB(a).then((b) {
completer.complete(b);
}).catchError((e) {
completer.completeError(e);
});
}).catchError((e) {
completer.completeError(e);
});
return completer.future;
}
4. 错误处理机制
Dart的Future错误处理有四层防护:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
void main() {
print('=== Future错误处理 ===');
// 方法1: then的第二参数
Future.error('错误1').then(
(value) => print('收到: $value'),
onError: (e) => print('onError: $e'), // 同步错误处理
);
// 方法2: catchError(推荐)
Future.error('错误2').then((value) {
print('收到: $value');
}).catchError((e, stackTrace) {
print('catchError: $e');
print(' 堆栈: ${stackTrace.toString().split('\n').take(3).join('\n ')}');
// 可以返回一个"恢复值"
return '默认值';
}).then((finalValue) {
print('最终值: $finalValue'); // "默认值"
});
// 方法3: 指定捕获的类型
Future<int>.error(FormatException('格式错误')).then((v) {
print('永远不会到这儿');
}).catchError((e) {
print('捕获特定错误: $e');
}, test: (e) => e is FormatException); // 只捕获FormatException
// 方法4: try/catch(async函数内)
Future<void> asyncVersion() async {
try {
final result = await fetchThatMightFail();
print('成功: $result');
} on TimeoutException catch (e) {
print('超时: $e');
} catch (e, st) {
print('其他错误: $e');
print('堆栈: $st');
} finally {
print('无论成功失败都执行');
}
}
}
Future<String> fetchThatMightFail() async {
final random = DateTime.now().millisecondsSinceEpoch % 3;
if (random == 0) return '数据';
if (random == 1) throw TimeoutException('请求超时');
throw Exception('未知错误');
}
错误处理的流程:
1
2
3
4
5
6
7
8
9
Future.error → then(() { ... }) → 跳过第一个then
→ 继续传播错误
→ catchError() 拦截
→ 返回新的值
→ 后续then正常执行
如果 catchError 不存在:
→ 错误传播到最外层
→ 未捕获的Future错误 → UnhandledFutureError
5. 并发控制:Future.wait 与 Future.any
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
void main() async {
print('=== 并发控制 ===\n');
// ---- Future.wait: 等待所有完成 ----
final results = await Future.wait([
fetchWithDelay('API-1', 3),
fetchWithDelay('API-2', 1),
fetchWithDelay('API-3', 2),
]);
print('所有API完成: $results'); // 总耗时约3秒(并行)
// ---- Future.any: 返回最快完成的 ----
final fastest = await Future.any([
fetchWithDelay('Fast-API', 0.5),
fetchWithDelay('Slow-API', 5),
]);
print('最快的API: $fastest'); // Fast-API(0.5秒)
// ---- Future.forEach: 顺序执行 ----
final items = ['A', 'B', 'C'];
await Future.forEach(items, (item) async {
await Future.delayed(Duration(milliseconds: 200));
print('处理: $item');
}); // A, B, C 顺序处理
// ---- 自定义并发限制 ----
final allItems = List.generate(20, (i) => 'Item $i');
await limitedConcurrency(allItems, 3, (item) async {
print('处理 [$item]');
await Future.delayed(Duration(milliseconds: 100));
return item.toUpperCase();
});
}
Future<String> fetchWithDelay(String name, double seconds) async {
await Future.delayed(Duration(milliseconds: (seconds * 1000).round()));
return '$name 结果';
}
/// 带并发限制的异步遍历
Future<List<R>> limitedConcurrency<T, R>(
List<T> items,
int limit,
Future<R> Function(T) worker,
) async {
final results = <R>[];
int index = 0;
// 启动多个worker
await Future.wait(List.generate(limit, (i) async {
while (true) {
int currentIndex;
// 线程安全地获取下一个任务
synchronized: {
currentIndex = index++;
}
// 直接用synchronized是伪代码,Dart单线程无需锁
// 这里只是展示逻辑
currentIndex = index++;
if (currentIndex >= items.length) break;
final result = await worker(items[currentIndex]);
results.add(result);
}
}));
return results;
}
实战案例:构建异步数据流水线
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// data_pipeline.dart - 使用Future构建的数据处理流水线
import 'dart:async';
import 'dart:math';
// ===== 流水线阶段(PipelineStage)=====
typedef Stage<I, O> = Future<O> Function(I input);
// ===== 数据流水线 =====
class AsyncPipeline<I, O> {
final List<Stage<dynamic, dynamic>> _stages;
AsyncPipeline._(this._stages);
/// 构建流水线
static _PipelineBuilder<I> from<I>(Stage<I, I> initial) {
return _PipelineBuilder<I>([initial]);
}
/// 执行流水线
Future<O> execute(I input) async {
dynamic current = input;
for (final stage in _stages) {
current = await stage(current);
}
return current as O;
}
}
// ===== 流水线构建器 =====
class _PipelineBuilder<T> {
final List<Stage<dynamic, dynamic>> _stages;
_PipelineBuilder(this._stages);
_PipelineBuilder<T2> then<T2>(Stage<T, T2> stage) {
return _PipelineBuilder<T2>([..._stages, stage]);
}
AsyncPipeline<T, T> build() => AsyncPipeline<T, T>._(_stages);
}
// ===== 具体阶段实现 =====
// 阶段1:数据验证
Future<Map<String, dynamic>> validateInput(
Map<String, dynamic> data) async {
print('[验证] 输入: $data');
await Future.delayed(Duration(milliseconds: 200));
if (data['id'] == null) {
throw ArgumentError('缺少id字段');
}
if (data['amount'] == null || (data['amount'] as num) <= 0) {
throw ArgumentError('无效的amount字段');
}
return data;
}
// 阶段2:数据转换
Future<Transaction> transform(Map<String, dynamic> data) async {
print('[转换] 处理数据');
await Future.delayed(Duration(milliseconds: 300));
return Transaction(
id: data['id'] as String,
amount: (data['amount'] as num).toDouble(),
currency: data['currency'] as String? ?? 'CNY',
timestamp: DateTime.now(),
category: data['category'] as String? ?? 'general',
);
}
// 阶段3:风控检查
Future<Transaction> riskCheck(Transaction tx) async {
print('[风控] 检查: ${tx.id}');
await Future.delayed(Duration(milliseconds: 500));
if (tx.amount > 100000 && tx.category == 'transfer') {
// 高风险交易
print('[风控] ⚠️ 大额转账,需要人工审核');
return tx.copyWith(flagged: true, flagReason: '大额转账');
}
return tx;
}
// 阶段4:持久化
Future<Transaction> persist(Transaction tx) async {
print('[持久化] 保存: ${tx.id}');
await Future.delayed(Duration(milliseconds: 200));
print('[持久化] ✅ 已保存');
return tx;
}
// ===== 数据模型 =====
class Transaction {
final String id;
final double amount;
final String currency;
final DateTime timestamp;
final String category;
final bool flagged;
final String? flagReason;
Transaction({
required this.id,
required this.amount,
this.currency = 'CNY',
DateTime? timestamp,
this.category = 'general',
this.flagged = false,
this.flagReason,
}) : timestamp = timestamp ?? DateTime.now();
Transaction copyWith({
String? id,
double? amount,
String? currency,
DateTime? timestamp,
String? category,
bool? flagged,
String? flagReason,
}) {
return Transaction(
id: id ?? this.id,
amount: amount ?? this.amount,
currency: currency ?? this.currency,
timestamp: timestamp ?? this.timestamp,
category: category ?? this.category,
flagged: flagged ?? this.flagged,
flagReason: flagReason ?? this.flagReason,
);
}
@override
String toString() {
final flag = flagged ? ' [FLAGGED: $flagReason]' : '';
return 'Transaction($id, $amount $currency, $category)$flag';
}
}
// ===== 主程序 =====
void main() async {
print('===== 异步数据流水线 =====\n');
// 构建流水线
final pipeline = AsyncPipeline
.from<Map<String, dynamic>>((data) async => data) // 初始阶段
.then(validateInput)
.then(transform)
.then(riskCheck)
.then(persist)
.build(); // 类型推断出的返回类型是 AsyncPipeline
// 正常交易
print('--- 交易1: 正常 ---');
final tx1Data = {
'id': 'TXN-001',
'amount': 1500.00,
'currency': 'USD',
'category': 'shopping',
};
try {
final result = await pipeline.execute(tx1Data);
print('最终结果: $result');
} catch (e) {
print('❌ 流水线异常: $e');
}
print('\n--- 交易2: 大额转账 ---');
final tx2Data = {
'id': 'TXN-002',
'amount': 500000.00,
'currency': 'CNY',
'category': 'transfer',
};
try {
final result = await pipeline.execute(tx2Data);
print('最终结果: $result');
} catch (e) {
print('❌ 流水线异常: $e');
}
print('\n--- 交易3: 无效数据 ---');
final tx3Data = {
'id': 'TXN-003',
'amount': -100,
};
try {
final result = await pipeline.execute(tx3Data);
print('最终结果: $result');
} catch (e) {
print('❌ 流水线异常: $e');
}
print('\n===== 流水线演示结束 =====');
}
底层原理(源码分析)
Dart事件循环(Event Loop)实现
Dart运行时维护了一个事件循环,它是所有异步调度的基础:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Dart事件循环的伪代码
class EventLoop {
final Queue<MicroTask> _microTaskQueue = Queue();
final Queue<Event> _eventQueue = Queue();
bool _running = true;
void run() {
while (_running) {
// 1. 优先处理所有微任务
while (_microTaskQueue.isNotEmpty) {
final microTask = _microTaskQueue.removeFirst();
microTask.execute();
// 如果执行微任务过程中添加了新微任务,继续处理
}
// 2. 处理一个事件队列任务
if (_eventQueue.isNotEmpty) {
final event = _eventQueue.removeFirst();
event.execute();
} else {
// 无事可做,等待新事件(阻塞)
waitForNewEvent();
}
}
}
}
Future的实现源码分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Dart SDK中Future的实现(简化自 sdk/lib/async/future.dart)
class Future<T> {
// Future的三种状态
static const int _statePending = 0; // 待定
static const int _stateValue = 1; // 已完成(值)
static const int _stateError = 2; // 已完成(错误)
int _state = _statePending;
T? _value;
Object? _error;
StackTrace? _stackTrace;
// 注册的回调链表
_FutureListener? _firstListener;
_FutureListener? _lastListener;
// then方法的实现
Future<R> then<R>(FutureOr<R> Function(T) onValue, {
Function? onError
}) {
// 创建新的Future来链接
final result = Future<R>();
// 创建监听器
final listener = _FutureListener<R, T>(
onValue: onValue,
onError: onError,
resultFuture: result,
);
// 如果Future已经完成,立即处理
if (_state != _statePending) {
_handleListener(listener);
} else {
// 加入监听器链表
_addListener(listener);
}
return result;
}
// Future完成时,处理所有注册的监听器
void _complete(T value) {
_state = _stateValue;
_value = value;
// 将监听器调度到微任务队列执行
var listener = _firstListener;
while (listener != null) {
_scheduleMicrotask(() => _handleListener(listener));
listener = listener.next;
}
_firstListener = null;
_lastListener = null;
}
}
async/await的编译器转换
Dart编译器将 async 函数转换为状态机:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 人类写的代码
Future<int> sumAsync(int a, int b) async {
await Future.delayed(Duration(seconds: 1));
return a + b;
}
// 编译器转换后的等效代码(概念近似)
Future<int> sumAsync(int a, int b) {
final _completer = Completer<int>();
int _step = 0;
void _run() {
switch (_step) {
case 0:
_step = 1;
// 执行到第一个await,注册回调
Future.delayed(Duration(seconds: 1)).then((_) => _run());
return; // 暂停
case 1:
// 从await恢复,继续执行
_step = 2;
final result = a + b;
_completer.complete(result);
return;
}
}
_run(); // 开始执行
return _completer.future;
}
Zone——错误的传播机制
Zone是Dart中的”异步上下文”,负责错误传播:
1
2
3
4
5
6
7
8
9
10
11
12
13
// 未捕获的Future错误如何被Zone拦截
void main() {
runZoned(() {
// 在这个Zone中创建的Future错误都会被捕获
Future.error('不会被全局捕获').then((_) {
// ...
});
// 但是如果没有catchError,错误会抛出到Zone
}, onError: (Object error, StackTrace stack) {
print('Zone捕获到未处理的Future错误: $error');
});
}
高频面试题解析
问题1:Future.delayed 和 Future(() => ...) 有什么区别?哪个先执行?
解析:
| 对比维度 | Future() | Future.delayed() |
|---|---|---|
| 调度时机 | 下一个事件循环 | 指定延迟后的事件循环 |
| 延迟 | 0(但仍是异步) | 自定义 |
| 执行顺序 | 比延迟0ms的delayed更快 | 取决于delay参数 |
执行顺序示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void main() {
print('1: main');
Future(() => print('2: Future()'));
Future.delayed(Duration.zero, () => print('3: delayed(0)'));
Future.microtask(() => print('4: microtask'));
// 输出: 1, 4, 2, 3
// 解释:microtask优先于事件队列
// Future()和Future.delayed(0)都在事件队列
// Future()的调度开销略低,所以早于delayed
}
底层差异:Future() 使用 Timer.run() 将任务调度到事件队列尾部。Future.delayed(Duration.zero, ...) 使用Timer机制,即使在0延迟下也有额外的Timer创建开销。
问题2:await 会阻塞当前线程吗?为什么Dart的单线程还能同时做多个事情?
解析:
await 不会阻塞线程。它只是暂停当前async函数的执行,将控制权交还给事件循环。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void main() {
print('1: 开始');
// 启动一个async函数但不等待
someAsyncWork();
print('3: main继续执行');
}
Future<void> someAsyncWork() async {
print('2: async函数开始');
await Future.delayed(Duration(seconds: 1));
// 这里暂停1秒,控制权交还给main的事件循环
print('4: 1秒后恢复执行');
}
执行流程:
1
2
3
4
5
6
7
8
9
10
11
12
13
时间 →
main()
├── print('1')
├── someAsyncWork()
│ ├── print('2')
│ └── await Future.delayed(1s) → 暂停
├── print('3')
└── main() 完成 (但事件循环继续)
1秒后 →
事件循环执行delayed的回调
├── 恢复 someAsyncWork()
│ └── print('4')
为什么能”同时做多个事情”? 因为await挂起的是当前async函数,事件循环可以继续处理其他事情——UI事件、其他Future的回调、定时器等。
类比:就像你在咖啡店排队(await),队伍暂停了但店里其他人还在活动(事件循环继续)。等到你的咖啡做好了(Future完成),你继续前进。
问题3:Future.wait 和 Future.any 有什么区别?各自的底层实现原理是什么?
解析:
区别:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Future.wait:等所有Future完成,收集所有结果
final all = await Future.wait([
fetchA(), // 1秒
fetchB(), // 2秒
fetchC(), // 3秒
]);
// 总耗时:3秒(并行执行,最慢的那个决定总时间)
// 结果:[A结果, B结果, C结果]
// Future.any:返回第一个完成的
final first = await Future.any([
fetchA(), // 1秒
fetchB(), // 2秒
fetchC(), // 3秒
]);
// 总耗时:1秒
// 结果:A结果(只返回第一个完成的)
底层实现原理(简化):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Future.wait 的极简实现
Future<List<T>> simpleWait<T>(List<Future<T>> futures) {
final completer = Completer<List<T>>();
final results = List<T?>.filled(futures.length, null);
int completed = 0;
bool hasError = false;
for (var i = 0; i < futures.length; i++) {
futures[i].then((value) {
if (hasError) return;
results[i] = value;
completed++;
if (completed == futures.length) {
completer.complete(results.cast<T>());
}
}).catchError((error) {
if (!hasError) {
hasError = true;
completer.completeError(error);
}
});
}
return completer.future;
}
// Future.any 的极简实现
Future<T> simpleAny<T>(List<Future<T>> futures) {
final completer = Completer<T>();
for (final future in futures) {
future.then((value) {
if (!completer.isCompleted) {
completer.complete(value);
}
}).catchError((error) {
if (!completer.isCompleted) {
completer.completeError(error);
}
});
}
return completer.future;
}
性能考量:
Future.wait内部使用_FutureWaitList管理所有结果,复杂度 O(n)Future.any所有Future同时运行,只取第一个,其他future仍在运行但结果被忽略- 两者都不会取消未完成的future——这是常见的误解。需要配合
abort或cancel逻辑
总结与扩展
核心要点
- Future状态机:Future有三个状态(pending / value / error),状态不可逆
- then链式调用:then返回新Future,实现异步操作的顺序组合;回调返回Future会被扁平化
- await语法糖:编译为状态机,挂起当前async函数但不阻塞线程
- 事件循环模型:Dart单线程通过事件循环(微任务→事件队列)实现异步
- 错误处理:catchError在链中拦截错误,未捕获的错误会传播到Zone
扩展思考
- Future vs Completer:Future是消费者侧(读),Completer是生产者侧(写),两者成对出现
- Stream与Future的区别:Future代表一次性的值,Stream代表多个值的序列。理解这个区别才知道何时用Future、何时用Stream
- Isolate与Future:Future只能在单线程内调度异步任务,跨线程计算需要使用Isolate
- Flutter中的Future:
setState()是在build方法中能否被调用?不行,因为build是同步的,不能在build中await - 进阶话题:
unawaited_futureslint规则——提醒开发者不要”fire and forget” Future,要么await,要么显式传给unawaited()