文章参考
一、获取一个Future

import 'package:http/http.dart' as http;
void _incrementCounter() {
http.get(Uri(host: 'www.baidu.com'));
}
/// get方法返回的就是一个Future
Future<Response> head(Uri url, {Map<String, String>? headers}) =>
_withClient((client) => client.head(url, headers: headers));
Future就像是一个承诺,以后会返回给一个Response对象,现在暂时没有,但是以后会返回一个。
Future就像是盒子里的巧克力糖,http.get请求就像返回一个Future,就像没有打开的盒子,当它有一天打开我们就能看看他里面有什么。
/// 打开之后我们可以用then看看盒子里装的是什么口味的糖
void _incrementCounter() {
http.get(Uri(host: 'www.baidu.com')).then((value) => null);
}
盒子打开也有可能是一种错误,比如网址输错
void _incrementCounter2() {
http.get(Uri(host: 'www.baidu.cn')).catchError((error) => null);
}
Future一共有三种状态:
- Future刚建成时没有完成的状态
- 正常完成时_.then得到一个值的状态
- 异常完成时_.catchError得到一个错误信息的状态
程序中大部分的异步操作都是围绕这三种状态进行的。
除了大量的网络和IO请求会给我们一个Future外,我们也可以自己获取一个Future
Future<String> getFuture() {
return Future(() => 'alice');
// 等待一秒钟返回值
// return Future.delayed(Duration(seconds: 1), () => 'alice');
}
void _incrementCounter() {
// 这里的操作都是异步的方式
getFuture().then((value) => print(value));
print('hi');
}
输出结果:
hi
alice
二、Future运行方式
直接运行的Future:
void main() {
print('main 1');
Future.sync(() => print('sync 1'));
Future.value(getName());
print('main2');
runApp(MyApp());
}
String getName() {
print('get name');
return 'bob';
}
输出结果:
main 1
sync 1
get name
main 2
Microtask
void main() {
scheduleMicrotask(() => print('microtask 1'));
Future.microtask(() => print('microtask 2'));
Future.value(123).then((value) => print('microtask 3'));
print('main 1');
Future.sync(() => print('sync 1'));
Future.value(getName());
print('main2');
runApp(MyApp());
}
String getName() {
print('get name');
return 'bob';
}
输出结果:
main 1
sync 1
get name
main2
microtask 1
microtask 2
microtask 3
可以看到直接运行的Future执行完后,Event Loop循环事件开始执行Mirtotask里的事件
Event
void main() {
// 等待一秒将打印事件加入Event
Future.delayed(Duration(seconds: 1), () => print('event 3'));
// 直接将打印事件加入Event
Future(() => print('event 1'));
// 等待0秒将打印事件加入Event
Future.delayed(Duration.zero, () => print('event 2'));
scheduleMicrotask(() => print('microtask 1'));
Future.microtask(() => print('microtask 2'));
Future.value(123).then((value) => print('microtask 3'));
print('main 1');
Future.sync(() => print('sync 1'));
Future.value(getName());
print('main2');
runApp(MyApp());
}
输出结果
main 1
sync 1
get name
main2
microtask 1
microtask 2
microtask 3
event 1
event 2
event 3
可以看到直接运行的Future执行完后,Event Loop循环事件开始执行Mirtotask里的事件。
只有当Microtask里的事件执行完,才会去执行Event里的事件
难点证明:
1.在已经完成的Future上会执行microtask
Future(() => print('event 1'));
scheduleMicrotask(() => print('microtask 1'));
Future.microtask(() => print('microtask 2'));
Future.value(123).then((value) => print('microtask 3'));
输出结果:
microtask 1
microtask 2
microtask 3
event 1
- 可以看到microtask 3 是在event 1前执行的,而event 1是第一个加入Event中的, microtask 3 先于event 1打印其事件必然添加到Micrtotask中的。
- Future.value(123)是立即执行的,这也就证明了证明了立即执行的Future,它的.then会往Microtask添加一个事件的。
2.一个普通的等待的Future,等待它完成的瞬间.then 会直接执行,不会多添加一次事件
Future.delayed(Duration(seconds: 1), () => print('delayed')).then((value) {
scheduleMicrotask(() => print('micro'));
print('then');
}).then((value) {
print('then 2');
});
输出结果:
delayed
then
then 2
micro
-
可以看到,等待1秒的Future,打印了delayed,往Microtask添加打印micro事件,再打印then,Future.then方法返回值也是Future,继续打印then2。
-
micro是第一个加入Microtask中的,它的优先级是高于Event的,所以then then2 想要先于micro打印,不可能继续往Microtask或Event中添加事件。
-
这也就证明了一个普通的等待的Future,等待它完成的瞬间.then 会直接执行,不会多添加一次事件
三、获取一个错误的Future
前面我们已经知道Future有,未完成,完成,错误三种状态,这里我们获取错误完成状态
void _incrementCounter() {
getFuture().then((value) => print(value));
}
Future<String> getFuture() {
return Future.error(Exception('something went wrong'));
}
输出结果:
Unhandled Exception: Exception: something went wrong
未处理的异常
void _incrementCounter() {
getFuture().then((value) => print(value)).catchError((err) => print(err));
}
Future<String> getFuture() {
return Future.error(Exception('something went wrong'));
}
输出结果:
Exception: something went wrong
没有说未处理过得异常
异常Future跑出异常并不会走.then而应该用.catchError捕获异常
void _incrementCounter() {
getFuture()
.then((value) => print(value))
.catchError((err) => print(err))
.whenComplete(() => print('complete'));
}
Future<String> getFuture() {
return Future.error(Exception('something went wrong'));
}
输出结果:
Exception: something went wrong
complete
Future运行完,不管是正常执行完,还是错误,都会执行.whenComplete
void _incrementCounter() {
getFuture()
.then((value) {
print(value);
return value * 2;
})
.then((value) => print(value))
.catchError((err) => print(err))
.whenComplete(() => print('complete'));
}
Future<int> getFuture() {
return Future.value(100);
}
输出结果:
100
200
complete
使用async修饰方法为异步方法,必须返回Future;await负责等待Future执行完
void _incrementCounter() async {
int id = await getFuture();
print(id);
id *= 2;
print(id);
}
Future<int> getFuture() async {
return 100;
}
输出结果:
100
200
void _incrementCounter() {
Future<int> id = getFuture();
print(id);
}
Future<int> getFuture() async {
return 100;
}
输出结果:
Instance of ‘Future<int>’
没有使用await直接获取的就是一个Future
使用async/await 异常捕获变得更加简洁,好处理
void _incrementCounter() async {
try {
int id = await getFuture();
print(id);
} catch (err) {
print('err:$err');
}
}
Future<int> getFuture() async {
throw 'oops';
}
输出结果:
err:oops

本文深入探讨了Dart编程语言中的Future概念,从获取Future、Future的运行方式到处理错误的Future,详细阐述了异步编程的关键点。通过实例展示了Future的三种状态(未完成、完成、错误)及其相互转换,同时讲解了如何利用then、catchError和whenComplete方法处理异步操作的结果和异常。此外,还介绍了async/await语法在简化异步代码和异常处理上的优势。

1953

被折叠的 条评论
为什么被折叠?



