跳转到内容
该页面尚未完工

Future 如 Stream 般飘来

这是两个写 Dart 异步时必然要用到的类,必须要明白的是,Dart 一般都是单线程的,除非自己开 Isolate

Future是一个类,可以用来做一些比较耗时的操作但不阻塞主线程,等到需要用其返回值时再用

Promise: ?

一般都是作为某个函数的返回类型,比如

Future<String> fetchUsername() { // 不显式指定这个<String>也是可以的,毕竟比较先进的语言都有自动推断类型吧(
// 模拟一个耗时操作,比如网络请求
return Future.delayed(Duration(seconds: 2), () => "Alice");
}

显然我们要返回一个Future对象,但是每次都包装一个太麻烦了,有没有更简单的方法呢?

有的兄弟,有的

async(异步)这个单词可以加在函数体外边,自动把返回值包装成Future对象,同时开一个线程让它稍后执行,比如这样

Future<String> fetchUsername() async {
Future.delayed(Duration(seconds: 2));
return 'Alice';
}

其实本质上就是把这个任务放到队列中去,等更重要的任务执行完再执行它

这可真是太方便了,可我们如果要用到返回值的时候该怎么办呢?

await可以一直等一个有Future的函数,唯一的问题是,你无法选中主线程,所以你只能让所在的有async的函数等一等,直到那个函数执行完返回你所需要的值

Future<void> fetchData() async { // 只能让async等一等
print("开始获取数据...");
String username = await fetchUsername(); // 等等fetchUsername()吧!
print("用户名:$username"); // 好耶得到这个值了
}

也就是通过保存这个函数的状态来“暂停”了这个函数的后续代码,直到await的函数结束(似是 Kotlin 来

和写多线程一样,写异步也很容易遇到各种妙妙异常,这时就得请出try-catch了。但是这玩意应该谁都会用吧,不写了哈哈

Stream也是一个类,也可以用来做一些比较耗时的操作但不阻塞主线程,等到需要用其返回值时再用,不同之处是它可以返回多个值,合适需要持续获取数据的时候用

用到这个的时候应该都会看用什么构造函数了吧(

去看看那一堆工厂构造函数就知道怎么得到一个Stream

async不同的是,async*可以让你得到一个Stream对象,就像下面这样

Stream<int> countStream() async* {
for (int i = 1; i <= 5; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}

发现了吗,和Future不同的是,Stream返回一个值需要用yield

然后我们遇到了和上面类似的问题:怎么拿到它的返回值呢?

此时你可能想到了await,但是先别急!我们可以直接用listen来监听:

countStream().listen(
(value) {
print('收到数据:$value');
},
onError: (error) {
print('发生错误:$error');
},
onDone: () {
print('Stream 已结束');
},
);

也就是加了几个监听器,来直接监听它

我们当然不能总是只用监听器的,不过也不能直接用await,而是用await for,它能像for-in一样持续遍历Stream的返回值