持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情
定义耗时操作
模拟一个网络请求,该网络请求耗时3秒,之后返回数据
void main(List<String> args) {
print("开始----");
print(DateTime.now());
print(getNetworkData());
print(DateTime.now());
print("结束----");
}
String getNetworkData() {
sleep(Duration(seconds: 3));
return "dart";
}
log:
网络请求阻塞 main()
函数,必须等待耗时操作完成才会执行之后的逻辑
关于 Future
什么是 Future
-
在 Dart 中,
Future
是指延迟运行的对象Future<T>
,用来表示在将来某时获取一个值的方式 -
这个
Future
对象是 Dart 内置的,有自己的队列策略,它将要操作的事件放入EventQueue
中,在队列中的事件按照先进先出的原则去逐一处理事件,当事件处理完成后,将结果返回给Future
对象void main(List<String> args) { print("开始----"); print(DateTime.now()); print(getNetworkData()); print(DateTime.now()); print("结束----"); } Future<String> getNetworkData() { return Future<String>(() { sleep(Duration(seconds: 5)); return "dart"; }); }
log:
将耗时操作放入
Future
对象中,没有出现阻塞现象,但是打印出的内容是Future
对象
Future 的回调函数
Future
的调用者可以注册回调
-
一种是成功回调函数。通过
.then()
的方式来监听Future
异步执行完成时获取到的结果 -
一种是错误回调函数。通过
.catchError()
的方式来监听Future
异步执行失败或者出现异常时的错误信息
void main(List<String> args) {
print("开始----");
print(DateTime.now());
final future = getNetworkData();
future.then((value) {
print(value);
}).catchError((error) {
print(error);
});
print(DateTime.now());
print("结束----");
}
Future<String> getNetworkData() {
return Future<String>(() {
sleep(Duration(seconds: 5));
// 返回正确的信息
return "dart";
// 返回错误的信息
// throw Exception("网络请求出现错误");
});
}
log:
正确信息
错误信息
Future 的状态
Future
在执行中,可以通过 whenComplete()
来监听 Future
是否执行完成。结果有两种状态
-
完成状态
当
Future
返回正确会错误的回调之后,代表Future
内部操作已完成,这个状态为完成状态 -
未完成状态
执行
Future
内部的操作时,还没有返回正确或错误的回调时的状态,这个状态为未完成状态
void main(List<String> args) {
print("开始----");
print(DateTime.now());
final future = getNetworkData();
future.then((value) {
print(value);
}).catchError((error) {
print(error);
}).whenComplete(() {
print("完成");
});
print(DateTime.now());
print("结束----");
}
Future<String> getNetworkData() {
return Future<String>(() {
sleep(Duration(seconds: 5));
// 返回正确的信息
return "dart";
// 返回错误的信息
// throw Exception("网络请求出现错误");
});
}
log:
Future 的链式调用
在某些情况下,可以在 then()
中继续返回值,会在下一个链式的 then()
调用回调函数中拿到返回的结果。但是当 Future
在完成时出现错误,而且它没有后续与之串起来的 Future
,则这个错误消息将会被转发给全局错误处理程序。这种机制确保了错误不会被自动删除,但是,这也意味着开发者应该尽早注册错误处理函数以便 Future
一旦返回 error
,error
处理程序就会立进行处理
void main(List<String> args) {
print("开始----");
print(DateTime.now());
final future = getNetworkData();
future.then((value) {
print(value);
return "dart2";
}).then((value) {
print(value);
}).catchError((error) {
print(error);
}).whenComplete(() {
print("完成");
});
print(DateTime.now());
print("结束----");
}
Future<String> getNetworkData() {
return Future<String>(() {
sleep(Duration(seconds: 5));
return "dart";
// throw Exception("网络请求出现错误");
});
}
log:
Future 的其他 API
-
Future.delayed(时间, 回调函数)
在延迟一定时间时执行回调函数,执行完回调函数后会执行
then()
和whenComplete()
的回调void main(List<String> args) { print("开始----"); Future.delayed(Duration(seconds: 3), () { return "延时3秒"; }).then((value) { print(value); }).whenComplete(() { print("完成"); }); print("结束----"); }
log:
-
Future.value(value)
直接获取一个完成的
Future
,该Future
会直接调用then()
的回调函数void main(List<String> args) { print("开始----"); Future.value("dart").then((value) { print(value); }); print("结束----"); }
log:
-
Future.error(object)
直接获取一个完成的
Future
,但是是一个发生异常的Future
,该Future
会直接调用catchError()
的回调函数void main(List<String> args) { print("开始----"); Future.error(Exception("错误信息")).catchError((error) { print(error); }); print("结束----"); }
log:
关于 async 和 await
async
:标记某个方法为异步方法(一般执行耗时操作),在声明方法的时候使用await
:等待某个异步方法执行完毕,是“等待”之意,所以要在调用耗时方法的时候使用
void main(List<String> args) {
print("开始----");
final future = getNetworkData();
future.then((value) {
print(value);
}).catchError((error) {
print(error);
}).whenComplete(() {
print("完成");
});
print("结束----");
}
Future<String> getNetworkData() async {
var reslut = await Future.delayed(Duration(seconds: 3), () {
const str = "dart";
print(str);
return str;
});
return "请求数据:" + reslut;
}
log:
步骤分析:
- 因为
Future.delayed()
返回的是一个Future
对象 - 在
Future.delayed()
函数前加await
,那么以下的逻辑就要等待Future.delayed()
的执行完毕出结果 await
关键字必须存在于async
函数中,所以需要将getNetworkData
函数定义成async
函数- 返回值是一个
Future
对象,如果没有返回Future
对象,会自动将返回值包装成Future
对象