发文时间:2022年04月13日 17:41:52 编辑:Aaron 标签:Flutter异步(Async) 图文详解系列 775
详细介绍Future的三种状态:未完成、正常完成和异常完成,最后也会介绍async await语法糖。
//案例如下 假设写一个关于http的get请求 import 'package:http/http.dart' as http; void _incrementCounter() { http.get(Uri(host: 'www.baidu.com')); } /// get方法返回的就是一个Future (以下为get源码) Future head(Uri url, {Map? headers}) => _withClient((client) => client.head(url, headers: headers));
在flutter中的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刚建成时没有完成的状态
正常完成时_.then得到一个值的状态
异常完成时_.catchError得到一个错误信息的状态
程序中大部分的异步操作都是围绕这三种状态进行的。
除了大量的网络和IO请求会给我们一个Future外,我们也可以自己获取一个Future
Future getFuture() { return Future(() => 'alice'); // 等待一秒钟返回值 // return Future.delayed(Duration(seconds: 1), () => 'alice'); } void _incrementCounter() { // 这里的操作都是异步的方式 getFuture().then((value) => print(value)); print('hi'); }
输出结果: hi alice
直接运行的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案例
String getName() { print('get name'); return 'bob'; } void _incrementCounter() async { // 等待一秒将打印事件加入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属于直接运行但是因为有scheduleMicrotask的存在 所以得 microtask运行完后按顺序执行 Future.value(123).then((value) => print('microtask 3')); print('main 1'); Future.sync(() => print('sync 1')); Future.value(getName()).then((value) => print(value)); print('main2'); runApp(M
输出结果: flutter: main 1 flutter: sync 1 flutter: get name flutter: main2 flutter: microtask 1 flutter: microtask 2 flutter: microtask 3 flutter: bob flutter: event 1 flutter: event 2 flutter: 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有,未完成,完成,错误三种状态,这里我们获取错误完成状态
void _incrementCounter() { getFuture().then((value) => print(value)); } Future 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 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 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 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 getFuture() async { return 100; } 输出结果: 100 200
void _incrementCounter() { Future id = getFuture(); print(id); } Future getFuture() async { return 100; } 输出结果: Instance of ‘Future’ 没有使用await直接获取的就是一个Future
使用async/await 异常捕获变得更加简洁,好处理
void _incrementCounter() async { try { int id = await getFuture(); print(id); } catch (err) { print('err:$err'); } } Future getFuture() async { throw 'oops'; } 输出结果: err:oops
多个then案例
void _incrementCounter() async { //可多个then操作 一步步操作 如读取数据库的操作,先获取用户id 然后通过用户id获取对应的信息等 Future.value(10) .then((value) { print('当前的值为 ${value}'); //通过return返回给下一级值 return value * 2; }) .then((value) { print('接收上一级来的value ${value}'); }) .catchError((error) => print('发生错误咯 ${error}')) .whenComplete(() => print('运行完成了')); runApp(MyApp()); } 输出 flutter: 当前的值为 10 flutter: 接收上一级来的value 20 flutter: 运行完成了
若无特殊说明,此文章为博主原创。 写稿不易,如需转载,请注明出处: https://www.aaroner.cn/art/52.html
Flutter教程- Async(二) Future就像是盒子里的巧克力糖
发文时间:2022年04月13日 17:41:52 编辑:Aaron 标签:Flutter异步(Async) 图文详解系列 775
详细介绍Future的三种状态:未完成、正常完成和异常完成,最后也会介绍async await语法糖。
1、获取一个Future
在flutter中的Future就像是一个承诺,以后会返回一个(Response)对象,只是现在暂时没有还在获取中,但是以后会返回一个。
Future就像是盒子里的巧克力糖,http.get请求就像返回一个Future,就像没有打开的盒子,当它有一天打开我们就能看看他里面有什么。
盒子打开也有可能会有错误,譬如网址错误
Future一共有三种状态:
Future刚建成时没有完成的状态
正常完成时_.then得到一个值的状态
异常完成时_.catchError得到一个错误信息的状态
程序中大部分的异步操作都是围绕这三种状态进行的。
除了大量的网络和IO请求会给我们一个Future外,我们也可以自己获取一个Future
二、Future运行方式
直接运行的Future
Microtask案例
Event案例
难点证明
1.在已经完成的Future上会执行microtask
可以看到microtask 3 是在event 1前执行的,而event 1是第一个加入Event中的, microtask 3 先于event 1打印其事件必然添加到Micrtotask中的。
Future.value(123)是立即执行的,这也就证明了证明了立即执行的Future,它的.then会往Microtask添加一个事件的。
2.一个普通的等待的Future,等待它完成的瞬间.then 会直接执行,不会多添加一次事件
可以看到,等待1秒的Future,打印了delayed,往Microtask添加打印micro事件,再打印then,Future.then方法返回值也是Future,继续打印then2。
micro是第一个加入Microtask中的,它的优先级是高于Event的,所以then then2 想要先于micro打印,不可能继续往Microtask或Event中添加事件。
这也就证明了一个普通的等待的Future,等待它完成的瞬间.then 会直接执行,不会多添加一次事件
三、获取一个错误的Future
前面我们已经知道Future有,未完成,完成,错误三种状态,这里我们获取错误完成状态
异常Future跑出异常并不会走.then而应该用.catchError捕获异常
Future运行完,不管是正常执行完,还是错误,都会执行.whenComplete
使用async修饰方法为异步方法,必须返回Future;await负责等待Future执行完
使用async/await 异常捕获变得更加简洁,好处理
多个then案例
若无特殊说明,此文章为博主原创。
写稿不易,如需转载,请注明出处: https://www.aaroner.cn/art/52.html