В Dart асинхронное программирование играет решающую роль в создании адаптивных и эффективных приложений. Одной из мощных функций является возможность конвертировать будущее в поток с помощью Stream.fromFuture
. В этой статье мы рассмотрим различные методы выполнения этой задачи, попутно предоставляя примеры кода и разговорные пояснения. Так что хватайте любимый напиток, садитесь поудобнее и давайте окунемся в мир будущих стримов в Dart!
Методы:
-
Метод 1: использование
Stream.fromFuture
:
Самый простой способ преобразовать будущее в поток — использовать конструкторStream.fromFuture
. Этот метод принимает в качестве аргумента одно будущее и возвращает поток, который генерирует одно событие после завершения будущего. Вот пример:Future<int> fetchData() async { // Simulating an asynchronous operation await Future.delayed(Duration(seconds: 2)); return 42; } void main() { final future = fetchData(); final stream = Stream.fromFuture(future); stream.listen((data) { print('Received data: $data'); }); }
В этом примере функция
fetchData
имитирует асинхронную операцию, которая возвращает значение42
. Мы конвертируем будущее, возвращаемоеfetchData
, в поток, используяStream.fromFuture
, а затем слушаем поток и печатаем полученные данные. -
Метод 2: использование
async*
иyield
:
Другой подход к преобразованию будущего в поток — использование функции-генератора сasync*
ключевое слово. Это позволяет нам создавать поток и генерировать несколько событий с течением времени. Вот пример:Stream<int> fetchDataAsStream() async* { // Simulating an asynchronous operation await Future.delayed(Duration(seconds: 2)); yield 42; } void main() { final stream = fetchDataAsStream(); stream.listen((data) { print('Received data: $data'); }); }
В этом примере функция
fetchDataAsStream
представляет собой функцию-генератор, обозначенную ключевым словомasync*
. Мы используемawait
для имитации асинхронной операции, а затемyield
для отправки данных. ФункцияfetchDataAsStream
возвращает поток, который выдает значение42
. Слушаем поток и распечатываем полученные данные. -
Метод 3: использование
Completer
иStreamController
:
Если вам нужен больший контроль над потоком и моментами, когда он генерирует события, вы можете использовать комбинацию изCompleter
иStreamController
. Вот пример:Future<int> fetchData() async { // Simulating an asynchronous operation await Future.delayed(Duration(seconds: 2)); return 42; } Stream<int> convertFutureToStream(Future<int> future) { final completer = Completer<int>(); final controller = StreamController<int>(); future.then((data) { completer.complete(data); controller.add(data); controller.close(); }).catchError((error) { completer.completeError(error); controller.addError(error); controller.close(); }); return controller.stream; } void main() { final future = fetchData(); final stream = convertFutureToStream(future); stream.listen((data) { print('Received data: $data'); }); }
В этом примере мы определяем функцию
convertFutureToStream
, которая принимает будущее в качестве аргумента. Внутри функции мы создаемcompleter
для завершения будущего иcontroller
для управления потоком. Мы используемthen
для обработки успешного завершения будущего и выдаем данные с помощьюcompleter
иcontroller
. В случае ошибки мы обрабатываем ее с помощьюcatchError
. Наконец, мы возвращаем поток изcontroller
. Затем мы можем прослушать поток и распечатать полученные данные.