dart-async-programming
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesedart-async-programming
Dart异步编程
Goal
目标
Implements robust, idiomatic asynchronous Dart code using and APIs. Manages concurrency, stream processing, and error handling while adhering to strict Dart async patterns, memory safety guidelines, and optimal execution flow.
FutureStream使用和 API编写健壮、符合惯用规范的Dart异步代码。在遵循严格的Dart异步模式、内存安全指南和最优执行流程的前提下,管理并发、流处理和错误处理。
FutureStreamDecision Logic
决策逻辑
When determining the appropriate asynchronous pattern, evaluate the following decision tree:
- Single Asynchronous Operation: Use with
Future<T>andasync.await - Multiple Independent Operations: Use to execute concurrently.
Future.wait - Sequence of Asynchronous Events: Use .
Stream<T>- Finite/Sequential Data (e.g., File I/O, Network Responses): Consume using .
await for - Infinite/Event-Driven Data (e.g., UI Events): Use on a Broadcast Stream.
listen()
- Finite/Sequential Data (e.g., File I/O, Network Responses): Consume using
- Custom Stream Generation:
- Simple Generation: Use and
async*.yield - Complex State/Event Management: Use .
StreamController
- Simple Generation: Use
确定合适的异步模式时,参考以下决策树进行评估:
- 单异步操作: 搭配和
async使用await。Future<T> - 多个独立操作: 使用并发执行。
Future.wait - 异步事件序列: 使用。
Stream<T>- 有限/顺序数据(例如文件I/O、网络响应): 使用消费。
await for - 无限/事件驱动数据(例如UI事件): 在广播流(Broadcast Stream)上调用。
listen()
- 有限/顺序数据(例如文件I/O、网络响应): 使用
- 自定义流生成:
- 简单生成: 使用和
async*。yield - 复杂状态/事件管理: 使用。
StreamController
- 简单生成: 使用
Instructions
使用说明
-
Implement Single Futures with Error Handling Always use/
asyncsyntax instead ofawait. Wrap operations in.then()blocks to handle exceptions gracefully.try-catchdartFuture<String> fetchUserData(String userId) async { try { final result = await api.getUser(userId); return result.name; } catch (e, stackTrace) { // Handle specific errors or rethrow logError('Failed to fetch user: $e', stackTrace); throw UserFetchException(e.toString()); } } -
Execute Independent Futures Concurrently When multiple asynchronous operations do not depend on each other, initiate them concurrently using.
Future.waitdartFuture<UserProfile> loadCompleteProfile(String userId) async { try { final results = await Future.wait([ api.getUser(userId), api.getUserPreferences(userId), api.getUserHistory(userId), ]); return UserProfile( user: results[0] as User, preferences: results[1] as Preferences, history: results[2] as History, ); } catch (e) { throw ProfileLoadException('Failed to load profile components: $e'); } } -
Consume Streams Sequentially Useto consume streams when you need to process events sequentially and wait for the stream to close.
await fordartFuture<int> calculateTotal(Stream<int> numberStream) async { int total = 0; try { await for (final number in numberStream) { total += number; } } catch (e) { logError('Stream processing failed: $e'); return -1; } return total; } -
Generate Streams using Generators For straightforward sequential event generation, useand
async*.yielddartStream<int> generateCountdown(int from) async* { for (int i = from; i >= 0; i--) { await Future.delayed(const Duration(seconds: 1)); yield i; } } -
Manage Complex Streams with StreamController When manually controlling stream state, instantiate a. You MUST ensure the controller is closed when no longer needed to prevent memory leaks.
StreamControllerdartclass DataManager { final StreamController<DataEvent> _controller = StreamController<DataEvent>.broadcast(); Stream<DataEvent> get dataStream => _controller.stream; void addData(DataEvent event) { if (!_controller.isClosed) { _controller.add(event); } } void dispose() { _controller.close(); } } -
Apply Stream Transformations and Timeouts Use built-in stream methods to handle errors, timeouts, and transformations before consumption.dart
Stream<String> processNetworkStream(Stream<List<int>> byteStream) async* { final safeStream = byteStream .handleError((e) => logError('Network error: $e')) .timeout( const Duration(seconds: 5), onTimeout: (sink) { sink.addError(TimeoutException('Stream timed out')); sink.close(); }, ) .transform(utf8.decoder) .transform(const LineSplitter()); await for (final line in safeStream) { if (line.isNotEmpty) yield line; } } -
Context Checkpoint STOP AND ASK THE USER: If the user requests stream implementation but does not specify if the stream will have multiple listeners (e.g., UI state) or a single listener (e.g., file reading), ask them to clarify before implementingor
StreamController.StreamController.broadcast() -
Validate-and-Fix After generating asynchronous code, perform a validation pass:
- Check: Are there any raw or
.then()chains? Fix: Convert to.catchError()/asyncandawait.try-catch - Check: Are multiple independent calls made sequentially? Fix: Combine them using
await.Future.wait - Check: Is a instantiated without a corresponding
StreamControllermethod in a disposal lifecycle? Fix: Add theclose()call.close()
- Check: Are there any raw
-
实现带错误处理的单个Future 始终使用/
async语法而非await。将操作包裹在.then()块中以优雅处理异常。try-catchdartFuture<String> fetchUserData(String userId) async { try { final result = await api.getUser(userId); return result.name; } catch (e, stackTrace) { // Handle specific errors or rethrow logError('Failed to fetch user: $e', stackTrace); throw UserFetchException(e.toString()); } } -
并发执行独立的Future 当多个异步操作互不依赖时,使用并发启动它们。
Future.waitdartFuture<UserProfile> loadCompleteProfile(String userId) async { try { final results = await Future.wait([ api.getUser(userId), api.getUserPreferences(userId), api.getUserHistory(userId), ]); return UserProfile( user: results[0] as User, preferences: results[1] as Preferences, history: results[2] as History, ); } catch (e) { throw ProfileLoadException('Failed to load profile components: $e'); } } -
顺序消费Stream 当你需要顺序处理事件并等待流关闭时,使用消费流。
await fordartFuture<int> calculateTotal(Stream<int> numberStream) async { int total = 0; try { await for (final number in numberStream) { total += number; } } catch (e) { logError('Stream processing failed: $e'); return -1; } return total; } -
使用生成器生成Stream 对于简单的顺序事件生成,使用和
async*。yielddartStream<int> generateCountdown(int from) async* { for (int i = from; i >= 0; i--) { await Future.delayed(const Duration(seconds: 1)); yield i; } } -
使用StreamController管理复杂Stream 当需要手动控制流状态时,实例化。你必须确保不再需要控制器时将其关闭,以防止内存泄漏。
StreamControllerdartclass DataManager { final StreamController<DataEvent> _controller = StreamController<DataEvent>.broadcast(); Stream<DataEvent> get dataStream => _controller.stream; void addData(DataEvent event) { if (!_controller.isClosed) { _controller.add(event); } } void dispose() { _controller.close(); } } -
应用Stream转换和超时设置 在消费流之前,使用内置的流方法处理错误、超时和转换。dart
Stream<String> processNetworkStream(Stream<List<int>> byteStream) async* { final safeStream = byteStream .handleError((e) => logError('Network error: $e')) .timeout( const Duration(seconds: 5), onTimeout: (sink) { sink.addError(TimeoutException('Stream timed out')); sink.close(); }, ) .transform(utf8.decoder) .transform(const LineSplitter()); await for (final line in safeStream) { if (line.isNotEmpty) yield line; } } -
上下文检查点 停止并询问用户: 如果用户请求实现流,但未指定流会有多个监听器(例如UI状态)还是单个监听器(例如文件读取),在实现或
StreamController之前请先询问用户明确需求。StreamController.broadcast() -
验证与修复 生成异步代码后,执行一次验证检查:
- 检查: 是否存在原生的或
.then()链?修复: 转换为.catchError()/async和await写法。try-catch - 检查: 是否有多个独立的调用顺序执行?修复: 使用
await合并它们。Future.wait - 检查: 实例化的是否在销毁生命周期中没有对应的
StreamController方法?修复: 添加close()调用。close()
- 检查: 是否存在原生的
Constraints
约束条件
- DO use /
asyncinstead of rawawaitcalls for better readability..then() - DO wrap asynchronous calls in to handle errors gracefully.
try-catch - PREFER to initiate multiple independent futures concurrently.
Future.wait - PREFER over
await fororforEachwhen consuming streams sequentially.listen - DO use with a
StreamControllercall to prevent memory leaks.close() - DO NOT use for UI event listeners, as UI frameworks send endless streams of events which will block execution indefinitely.
await for - Related Skills: ,
dart-idiomatic-usage.dart-concurrency-isolates
- 务必使用/
async而非原生await调用,以获得更好的可读性。.then() - 务必将异步调用包裹在中,以优雅处理错误。
try-catch - 优先使用并发启动多个独立的Future。
Future.wait - 顺序消费流时,优先使用而非
await for或forEach。listen - 务必为添加
StreamController调用,以防止内存泄漏。close() - 请勿为UI事件监听器使用,因为UI框架会发送无限的事件流,会无限期阻塞执行。
await for - 相关技能:、
dart-idiomatic-usage。dart-concurrency-isolates