今天我们来学Dart中的异步编程和Future
异步编程

这里我们简单描述一下进程和线程
进程和线程
进程就是正在运行中的程序,因为电脑上的软件是存在在磁盘上的,即以文件的形式存储的,也就是我们熟悉的文件夹,包括手机平板也是同样的,当我们点开一个软件时,首先这个软件会被加载到内存并获得系统资源,然后开始执行
你使用ctrl + alt +del 打开你的资源管理器就明白了(话说我后台怎么这么多程序,难道是开机自启动? 难怪每次开机这么慢)

程序运行会占用内存,每个进程之间内存隔离互不影响,比如你终止了哔哩哔哩的进程,不会影响其他软件的使用

至于线程,就是程序内部的执行路线,单个进程里有至少一个线程,以浏览器为例
Chrome(进程)
├── 线程1:渲染页面
├── 线程2:网络下载
├── 线程3:执行 JavaScript
└── 线程4:播放音频
即进程给程序分配资源,线程负责执行程序
多线程就是多个线程同时进行执行任务,效率更高,但是单线程就是排队执行任务,上一个任务执行完毕才会轮到下一个
Future

正常情况下是这样的,这里用了回调函数

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void main(List<String> args) { Future f = Future(() { return "baka"; throw Exception(); });
f.then((value) { print(value); }); f.catchError((err) { print("出~错~了 ! zako~ zako~ zako~"); }); }
|
异常情况下是这样的

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void main(List<String> args) { Future f = Future(() { throw Exception(); });
f.then((value) { print(value); }); f.catchError((err) { print("出~错~了 ! zako~ zako~ zako~"); }); }
|
Flutter的链式调用
上一个 then 返回对象,会在下一个 then 中接收
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void main(List<String> args) { Future f = Future(() { return "baka_00"; });
f .then((value) { return Future(() => "baka_01"); }) .then((value) { return Future(() => "$value----baka_02"); }) .then((value) { return Future(() => "$value----baka_03"); }) .then((value) { print(value); }) .catchError((err) { print("出~错~了 ! zako~ zako~ zako~"); }); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| void main() { Future.value(10) .then((value) { print("第1步收到:$value");
return value + 5; }) .then((value) { print("第2步收到:$value");
return value * 2; }) .then((value) { print("第3步收到:$value"); }) .catchError((error) { print("发生错误:$error"); }); }
|
async和await

你可以发现在函数的参数括号后面有async 指的是 asynchronous(异步),代表当前函数是异步的
| 关键字 |
作用 |
| async |
声明函数是异步 |
| await |
等待异步结果 |
1 2 3 4 5 6 7 8
| Future<String> getName() async { return "Tom"; }
void main() async { var name = await getName(); print(name); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| Future<String> fetchData() async { await Future.delayed(Duration(seconds: 2)); return "数据加载完成"; }
void main() async { print("开始请求");
var data = await fetchData();
print(data); print("结束"); }
|
这里你可以注意到一行代码 Future.delayed(Duration(seconds: 2));
这里其实完整格式是
(new) Future<String>.delayed(Duration duration, [FutureOr<String> Function()? computation])
其中第一个参数Duration duration是指延迟时间例如延迟一秒钟Duration(seconds: 1)
而第二个参数是可选的,即延迟时间之后的返回值,通常为 匿名函数()=>{ return 返回值 },这里的返回值必须和泛型里规定的一致
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
| Future<String> getUser() async { return Future.delayed(Duration(seconds: 1), () { return "Tom"; }); }
Future<String> getOrder(String user) async { return Future.delayed(Duration(seconds: 1), () { return "$user 的订单:iPhone"; }); }
Future<String> getDetail(String order) async { return Future.delayed(Duration(seconds: 1), () { return "$order(128GB)"; }); }
void main() async {
print("开始请求");
var user = await getUser(); print("用户:$user");
var order = await getOrder(user); print("订单:$order");
var detail = await getDetail(order); print("详情:$detail");
print("结束");
}
|
try catch
这个和C#里的很像,C#里也有try catch函数,这里 try 指的是 尝试(try block) 而catch指的是 捕获(catch exception)
1 2 3 4 5 6 7 8 9
| void main() { try { int a = 10 ~/ 0;
print(a); } catch (e) { print("出错了:$e"); } }
|
在异步里就是
1 2 3 4 5 6 7 8 9 10 11 12 13
| Future<String> getData() async { throw Exception("网络挂了"); }
void main() async { try { var data = await getData();
print(data); } catch (e) { print("捕获到错误:$e"); } }
|
其实和if lese的逻辑差不多,只不过这个是应对错误情况使用的
on关键字
这个其实在之前我们学mixin的时候就遇到了,不过on关键字在不同场景下的作用不太一样
在try on中
我们刚才说的try catch的catch的参数是error,也就是接受一切错误并反馈
但是这里try on 就不是了
在这里 on = 只捕获某种指定类型的异常
1 2 3 4 5 6
| try { ... } on 异常类型 { ... }
|
例如刚才的这个例子返回值是 IntegerDivisionByZeroException

而我们只提取这一个问题并输出就行了
1 2 3 4 5 6 7 8 9
| void main() { try { int a = 10 ~/ 0;
print(a); } on IntegerDivisionByZeroException { print("不能除0"); } }
|

甚至还能这样玩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| void main() { try { List list = [1, 2]; print(list[5]); }on RangeError { print("越界"); }
try { int a = 10 ~/ 0; } on IntegerDivisionByZeroException { print("除零"); }
try { int.parse("abc"); } on FormatException { print("格式错误"); } }
|
在mixin中
在mixin中我们知道with关键字可以让类使用mixin里的参数和方法
而我们在mixin中使用on就是限制只有哪些类可以使用这个mixin
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
| class Animal { void eat() { print("动物吃东西"); } }
class Bird extends Animal { void layEgg() { print("鸟下蛋"); } }
class Cat extends Animal {}
class Dog extends Animal {}
mixin Fly on Bird { void fly() { eat();
layEgg();
print("鸟在飞"); } }
class Sparrow extends Bird with Fly {}
void main() { Sparrow s = Sparrow();
s.fly(); }
|
评论区