Flutter异步async操作--Future

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

文章参考

王叔不秃

一、获取一个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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值