Flutter中如何编写链式调用的异步函数?Node.js开发者求助
Dart异步函数问题解答与代码修正
原代码编译错误分析与修正
错误原因
- 第一个错误:
then((exists) => { ... })中,Dart里箭头函数后接大括号会被解析为Set字面量而非函数体,同时throw UnsupportedException();末尾的分号多余,导致语法错误。 - 第二个错误:
directory.exists()返回Future<bool>,后续的then回调需要接收bool类型参数,但原代码中() => directory.list()没有接收参数,且directory.list()返回Stream而非Future,类型不匹配导致报错。
修正后的代码(两种写法)
写法1:使用async/await(更简洁易读,推荐)
import 'dart:io'; import '../exception/UnsupportedException.dart'; import '../domain/InfoDTO.dart'; class InfoService { static final String INFO_PATH = '/foo'; Future<List<InfoDTO>> findAll() async { final directory = Directory(INFO_PATH); final exists = await directory.exists(); if (!exists) { throw UnsupportedException(); } final stream = directory.list(); final list = await stream.map<InfoDTO>((entity) => InfoDTO(entity.path)).toList(); return list; } }
写法2:使用then链式调用(贴近Node.js习惯)
import 'dart:io'; import '../exception/UnsupportedException.dart'; import '../domain/InfoDTO.dart'; class InfoService { static final String INFO_PATH = '/foo'; Future<List<InfoDTO>> findAll() { final directory = Directory(INFO_PATH); return directory.exists() .then((exists) { if (!exists) throw UnsupportedException(); return directory.list(); }) .then((stream) => stream.map<InfoDTO>((entity) => InfoDTO(entity.path))) .then((stream) => stream.toList()); } }
注意:原代码中手动创建Completer是多余的,Dart的then链本身会返回Future,无需额外包裹。
疑问解答
1. Dart中能否链式调用多个then函数?
可以,和Node.js的Promise链式调用逻辑一致,每个then的返回值会作为下一个then的输入。但要注意:
- 每个
then的回调参数类型必须匹配上一个then的返回值类型; - 如果
then中抛出异常,后续的then会被跳过,直接进入catchError。
2. 是否可以像示例那样直接返回Directory的Future函数?
可以,示例中的NetworkService代码是合法的:
Directory(SYS_NET_PATH).list()返回Stream<FileSystemEntity>;stream.map(...)转换为Stream<NetworkInterface>;stream.toList()返回Future<List<NetworkInterface>>,与方法的返回类型完全匹配。
不过同样推荐用async/await简化代码:
class NetworkService { static final String SYS_NET_PATH = '/sys/class/net'; Future<List<NetworkInterface>> findAllNetworkInterfaces() async { final stream = Directory(SYS_NET_PATH).list(); return await stream.map<NetworkInterface>((entity) => NetworkInterface(entity.path, entity.path)).toList(); } }
3. 是否可以通过示例方式捕获异步函数的错误?
可以,catchError会捕获整个then链中抛出的所有异常,包括findAll函数中抛出的UnsupportedException,示例中的写法是正确的。另外也可以用try/catch结合async/await实现同样的逻辑:
@override void initState() { super.initState(); _loadData(); } void _loadData() async { try { final items = await infoService.findAll(); setState(() { _items = items; _loading = false; }); } catch (e) { setState(() { _error = e; _loading = false; }); } }
内容的提问来源于stack exchange,提问作者e-info128
相关产品推荐
相关产品推荐

