Dart-异步编程

2021-07-28  本文已影响0人  AilurusFulgens

isolate

Dart是基于单线程模型的语言。
但是我们在开发中也会有请求网络这样的耗时操作,所以Dart也有并发机制,称为isolate
Dart中的isolate无法共享内存。

Future

通常异步函数返回的对象就是一个Future
当一个Future执行完后,可以使用then()来处理返回的结果。
Future对象其实就代表了在事件队列中的一个事件的结果。

基本使用

File(r"D:\xxx\xxx\xxx.txt")
    // File().readAsString()返回Future<String>
    .readAsString()
    // 可使用then来接收Future<String>返回的值
    .then((value) => print(value))
    // 可使用catchError来捕获异常信息
    .catchError((s) => print(s));

串行组合

File(r"D:\xxx\xxx\xxx.txt").readAsString().then(
  (value) {
    print(value);
    return 1; //return将转换为Future<int>返回,所以后续可以继续使用then调用
  },
).then((value) => print(value));

并行组合

Future f1 = Future.delayed(Duration(seconds: 3), () {
  return 1;
});
Future f2 = Future.delayed(Duration(seconds: 5), () {
  return 3;
});
Future.wait([f1, f2]).then((value) {
  print(value[0]); // 返回f1的值
  print(value[1]); // 返回f2的值
});

async & await

可以使用asyncawait关键字,将异步代码写成同步的形式,可以有效得解决回调地狱的问题。
await必须在async方法内使用。
该方法必须返回voidFuture;如果该方法返回值是一个Future,则将自动转换。

void main() async {
  var result = await readTxt();
  print(result);
}

Future<String> readTxt() async {
  var result = await File(r"D:\xxx\xxx\xxx.txt").readAsString();
  // 可以使用async和await关键字,将异步代码写成同步的形式,可以有效得解决回调地狱的问题
  // await必须在async方法内使用
  print(result.runtimeType);
  print(result);
  // 如果该方法返回值是一个Future,则将自动转换
  return result;
}

Stream

Stream是一个异步数据源,是处理异步事件流的统一API。

单订阅模式

// 通过Stream打开文件
Stream<List<int>> stream = File(r"D:\xxx\xxx\xxx.txt").openRead();

/// 默认单订阅模式
// 设置监听,返回一个订阅者
var listen = stream.listen((event) {
  print("listen");
});
// 调用cancel方法取消订阅
listen.cancel();
// onData会替换掉之前设置的listen或onData方法
listen.onData((data) {
  print("onData");
});
// onData会在订阅者完成所有通知后执行,即可以做收尾工作
listen.onDone(() {
  print("onDone");
});
// 暂停订阅者
listen.pause();
// 恢复订阅者
listen.resume();
// 单订阅模式不支持添加两个订阅者,会抛异常
var listen2 = stream.listen((event) {
  print("listen2");
});

单订阅模式不支持添加两个订阅者,会抛异常

广播模式(多订阅)

// 通过Stream打开文件
Stream<List<int>> stream = File(r"D:\xxx\xxx\xxx.txt").openRead();

/// 广播模式:多订阅
/// 广播可由单订阅转换而来
var broadcastStream = stream.asBroadcastStream();
broadcastStream.listen((event) {
  print("broadcastStream 1");
});
broadcastStream.listen((event) {
  print("broadcastStream 2");
});
broadcastStream.listen((event) {
  print("broadcastStream 3");
});

/// 直接创建一个广播
var controller = StreamController.broadcast();
// 发送一个消息
controller.add("1");
// 设置一个监听(设置监听前发送消息无法收到)
controller.stream.listen((event) {
  print('接受广播内容:$event');
});
// 广播用完记得close
controller.close();

由单订阅转换的广播本质还是单订阅流,所以添加订阅者不会导致消息丢失;
直接由StreamController创建的广播,后注册的订阅者无法收到之前发出的消息。

上一篇下一篇

猜你喜欢

热点阅读