Dart 提供了多种方式来实现,包括以下几种
1、使用 Future.wait():Future.wait() 函数可以接收多个 Future 对象,并返回一个 Future 对象,该对象在所有 Future 对象都完成后才会完成。这样,我们可以使用该函数来等待多个异步操作完成后再进行下一步操作。
Future<void> fetchData() async {
try {
var response1 = http.get(Uri.parse('https://example.com/data1'));
var response2 = http.get(Uri.parse('https://example.com/data2'));
var results = await Future.wait([response1, response2]);
var data1 = jsonDecode(results[0].body);
var data2 = jsonDecode(results[1].body);
print(data1);
print(data2);
} catch (e) {
print('Error: $e');
}
}
使用 Completer,它可以用于等待多个 Future 对象的完成,并在所有 Future 对象都完成后返回结果。使用 Completer,我们可以将多个异步请求的 Future 对象添加到 Completer 中,并通过监听 Completer 的 future 属性来等待所有 Future 对象的完成。
Future<void> fetchData() async {
try {
var completer = Completer<List<dynamic>>();
var response1 = http.get(Uri.parse('https://example.com/data1'));
var response2 = http.get(Uri.parse('https://example.com/data2'));
Future.wait([response1, response2]).then((results) {
var data1 = jsonDecode(results[0].body);
var data2 = jsonDecode(results[1].body);
completer.complete([data1, data2]);
});
var results = await completer.future;
print(results[0]);
print(results[1]);
} catch (e) {
print('Error: $e');
}
}
2、使用 Stream 和 StreamController:Stream 和 StreamController 是 Dart 中用于处理流的类,它们可以用于实现多个异步请求的并发处理和结果组合。我们可以创建多个 StreamController,并将它们的流合并到一个单独的流中,然后使用 Stream 的各种操作符来处理结果。
Future<void> fetchData() async {
try {
var controller1 = StreamController();
var controller2 = StreamController();
http.get(Uri.parse('https://example.com/data1'))
.then((response) => controller1.add(response.body));
http.get(Uri.parse('https://example.com/data2'))
.then((response) => controller2.add(response.body));
var results = await StreamZip([controller1.stream, controller2.stream]).toList();
var data1 = jsonDecode(results[0]);
var data2 = jsonDecode(results[1]);
print(data1);
print(data2);
} catch (e) {
print('Error: $e');
}
}
3、使用 async* 和 yield:async* 和 yield 是 Dart 中用于创建异步生成器的语法,它们可以用于实现多个异步请求的串行处理和结果组合。我们可以使用 yield 关键字将每个异步请求的结果返回给调用方,从而实现异步请求的串行处理。
Stream<String> fetchData() async* {
try {
var response1 = await http.get(Uri.parse('https://example.com/data1'));
var data1 = jsonDecode(response1.body);
yield data1.toString();
var response2 = await http.get(Uri.parse('https://example.com/data2'));
var data2 = jsonDecode(response2.body);
yield data2.toString();
} catch (e) {
print('Error: $e');
}
}
4、使用 Isolate:Isolate 是 Dart 中的一种轻量级进程,它可以与其他 Isolate 并行执行,并且与其他 Isolate 共享内存空间。通过使用 Isolate,我们可以在多个独立的 Isolate 中同时执行多个异步请求,并将结果传回主 Isolate 进行处理。
import 'dart:isolate';
void fetchData(SendPort sendPort) async {
try {
var response1 = await http.get(Uri.parse('https://example.com/data1'));
var data1 = jsonDecode(response1.body);
var response2 = await http.get(Uri.parse('https://example.com/data2'));
var data2 = jsonDecode(response2.body);
sendPort.send([data1, data2]);
} catch (e) {
sendPort.sendError('Error: $e');
}
}
Future<void> main() async {
try {
var receivePort = ReceivePort();
await Isolate.spawn(fetchData, receivePort.sendPort);
var results = await receivePort.first;
print(results[0]);
print(results[1]);
} catch (e) {
print('Error: $e');
}
}
使用第三方插件
1、dio:dio 是一个强大的 Dart HTTP 客户端,它支持多个并发请求,并提供了丰富的功能,如拦截器、请求和响应转换等。 这个是最常用的
Future<void> fetchData() async {
try {
var dio = Dio();
var response1 = await dio.get('https://example.com/data1');
var data1 = response1.data;
var response2 = await dio.get('https://example.com/data2');
var data2 = response2.data;
print(data1);
print(data2);
} catch (e) {
print('Error: $e');
}
}
2、http_multi_client:http_multi_client 是一个支持并发请求的 Dart HTTP 客户端,它可以在同一个域名下创建多个连接来提高请求效率。
Future<void> fetchData() async {
try {
var client = MultiClient();
var response1 = await client.get(Uri.parse('https://example.com/data1'));
var data1 = jsonDecode(response1.body);
var response2 = await client.get(Uri.parse('https://example.com/data2'));
var data2 = jsonDecode(response2.body);
print(data1);
print(data2);
client.close();
} catch (e) {
print('Error: $e');
}
}
3、flutter_bloc:flutter_bloc 是一个 Flutter 状态管理库,它提供了一种基于 BLoC 模式的方式来处理异步请求。使用 flutter_bloc,我们可以将多个异步请求的结果保存到一个或多个状态对象中,并在 UI 层中根据状态来更新界面。
class DataBloc extends Bloc<DataEvent, DataState> {
@override
DataState get initialState => DataLoading();
@override
Stream<DataState> mapEventToState(DataEvent event) async* {
if (event is FetchData) {
try {
var response1 = await http.get(Uri.parse('https://example.com/data1'));
var data1 = jsonDecode(response1.body);
var response2 = await http.get(Uri.parse('https://example.com/data2'));
var data2 = jsonDecode(response2.body);
yield DataLoaded([data1, data2]);
} catch (e) {
yield DataLoadFailure('Error: $e');
}
}
}
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<DataBloc, DataState>(
builder: (context, state) {
if (state is DataLoading) {
return CircularProgressIndicator();
} else if (state is DataLoaded) {
return Column(
children: [
Text(state.data[0]),
Text(state.data[1]),
],
);
} else if (state is DataLoadFailure) {
return Text(state.error);
} else {
return Text('Unknown state');
}
},
);
}
}