Xử lý lỗi trong Dart Stream
Đầu tiên, chúng ta hãy xem một ví dụ để biết điều gì sẽ xẩy ra khi một lỗi trên Stream không được xử lý.
ex1.dart
Stream<int> getIntStream() async* {
for (int i = 0; i < 5; i++) {
await Future.delayed(Duration(seconds: 2));
if (i == 2) {
throw Exception('My Custom Error!');
}
yield i;
}
}
Future<void> main() async {
Stream<int> myStream = getIntStream();
await for (int value in myStream) {
print("Value: $value");
}
}
Value: 0
Value: 1
Unhandled exception:
Exception: My Custom Error!
#0 getIntStream (package:dart_14669_stream_error_handling/ex1.dart:5:7)
<asynchronous suspension>
#1 main (package:dart_14669_stream_error_handling/ex1.dart:14:3)
<asynchronous suspension>

1. Stream.handleError()
Phương thức handleError() của Stream tạo ra một Stream khác bao bọc lấy Stream hiện tại và xử lý các sự kiện lỗi.
Định nghĩa: | Nội dung: |
handleError() **
| handleError() **
|
bool test(dynamic error)? |
|
Function onError
| Khi lỗi được chuyển tới hàm onError() để xử lý, bạn có thể có các lựa chọn sau:
|
Trong ví dụ này, việc ném ra một lỗi trong hàm async* sẽ làm kết thúc Stream. Ném ra một lỗi không phải là cách để đặt một sự kiện lỗi lên Stream.
error_handling_ex1.dart
Stream<int> getIntStream() async* {
for (int i = 0; i < 5; i++) {
await Future.delayed(Duration(seconds: 2));
if (i == 2) {
throw Exception('My Custom Error!');
}
yield i;
}
}
Future<void> main() async {
Stream<int> intStream = getIntStream();
Stream<int> wrappedStream = intStream.handleError(
(Object error, StackTrace stackTrace) {
print("Handle error in onError function: $error");
},
);
await for (int value in wrappedStream) {
print("Value: $value");
}
}
Value: 0
Value: 1
Handle error in onError function: Exception: My Custom Error!
2. Thêm sự kiện lỗi vào Stream
Các ví dụ ở trên cho thấy rằng việc ném ra một lỗi trong hàm async* có thể làm kết thúc Stream. Trong phần này chúng ta sẽ thảo luận về các cách thông dụng để đặt một sự kiện lỗi lên Stream.
Về cơ bản, bạn có thể lựa chọn một trong các giải pháp sau:
- yield* Stream.error(errorObject);
- yield* Stream.fromFuture(Future.error(Exception());
- yield* () async* { throw Exception(); }();
yield* Stream.error()
Sử dụng yield* Stream.error() để thêm một sự kiện lỗi vào Stream thay vì ném ra một lỗi.
ex2.dart
Stream<int> getIntStream() async* {
for (int i = 0; i < 5; i++) {
await Future.delayed(Duration(seconds: 2));
if (i == 2 || i == 3) {
yield* Stream.error('My Custom Error at index $i!');
}
yield i;
}
}
Future<void> main() async {
Stream<int> intStream = getIntStream();
await for (int value in intStream) {
print("Value: $value");
}
}
Kết quả chạy ví dụ ở trên cho thấy, nếu một sự kiện lỗi trên Stream không được xử lý nó sẽ làm kết thúc Stream:
Value: 0
Value: 1
Unhandled exception:
My Custom Error at index 2!
Chúng ta sẽ sửa lại ví dụ trên một chút, sử dụng phương thức handleError() để xử lý lỗi.
error_handling_ex2.dart
Stream<int> getIntStream() async* {
for (int i = 0; i < 5; i++) {
await Future.delayed(Duration(seconds: 2));
if (i == 2 || i == 3) {
yield* Stream.error('My Custom Error at index $i!');
}
yield i;
}
}
Future<void> main() async {
Stream<int> intStream = getIntStream();
Stream<int> wrappedStream = intStream.handleError(
(Object error, StackTrace stackTrace) {
print("Handle error in onError function: $error");
},
);
await for (int value in wrappedStream) {
print("Value: $value");
}
}
Output:
Value: 0
Value: 1
Handle error in onError function: My Custom Error at index 2!
Value: 2
Handle error in onError function: My Custom Error at index 3!
Value: 3
Value: 4
Chúng ta sửa lại ví dụ trên một chút nữa để đảm bảo rằng một sự kiện hoặc là một lỗi hoặc là một dữ liệu (Không thể là cả hai).
error_handing_ex2b.dart
Stream<int> getIntStream() async* {
for (int i = 0; i < 5; i++) {
await Future.delayed(Duration(seconds: 2));
if (i == 2 || i == 3) {
yield* Stream.error('My Custom Error at index $i!');
} else {
yield i;
}
}
}
Future<void> main() async {
Stream<int> intStream = getIntStream();
Stream<int> wrappedStream = intStream.handleError(
(Object error, StackTrace stackTrace) {
print("Handle error in onError function: $error");
},
);
await for (int value in wrappedStream) {
print("Value: $value");
}
}
Output:
Value: 0
Value: 1
Handle error in onError function: My Custom Error at index 2!
Handle error in onError function: My Custom Error at index 3!
Value: 4
yield* Stream.fromFuture(Future.error(Exception())
error_handing_ex3.dart
Stream<int> getIntStream() async* {
for (int i = 0; i < 5; i++) {
await Future.delayed(Duration(seconds: 2));
if (i == 2 || i == 3) {
yield* Stream.fromFuture(
Future<int>.error(
Exception("My Custom Error at index $i!"),
),
);
} else {
yield i;
}
}
}
Future<void> main() async {
Stream<int> intStream = getIntStream();
Stream<int> wrappedStream = intStream.handleError(
(Object error, StackTrace stackTrace) {
print("Handle error in onError function: $error");
},
);
await for (int value in wrappedStream) {
print("Value: $value");
}
}
Output:
Value: 0
Value: 1
Handle error in onError function: Exception: My Custom Error at index 2!
Handle error in onError function: Exception: My Custom Error at index 3!
Value: 4
yield* () async* { throw Exception(); }();
error_handing_ex4.dart
Stream<int> getIntStream() async* {
for (int i = 0; i < 5; i++) {
await Future.delayed(Duration(seconds: 2));
if (i == 2 || i == 3) {
yield* () async* {
throw Exception("My Custom Error at index $i!");
}() as Stream<int>;
} else {
yield i;
}
}
}
Future<void> main() async {
Stream<int> intStream = getIntStream();
Stream<int> wrappedStream = intStream.handleError(
(Object error, StackTrace stackTrace) {
print("Handle error in onError function: $error");
},
);
await for (int value in wrappedStream) {
print("Value: $value");
}
}
3. Stream.transform()
Phương thức transform() được sử dụng để chuyển đổi Stream<T> hiện tại thành Stream<S>. Bằng cách sử dụng phương thức này bạn có thể biến đổi một sự kiện lỗi trên Stream<T> thành một sự kiện dữ liệu trên Stream<S>.
Stream<S> transform<S>(StreamTransformer<T, S> streamTransformer)
Trong ví dụ này chúng ta chuyển đổi một Stream<int> thành một Stream<String>, với các sự kiện lỗi trên Stream<int> sẽ được chuyển đổi thành một String mặc định.
transform_ex1.dart
import 'dart:async';
Stream<int> getIntStream() async* {
for (int i = 0; i < 5; i++) {
await Future.delayed(Duration(seconds: 2));
if (i == 2 || i == 3) {
yield* Stream.error('My Custom Error at index $i!');
} else {
yield i;
}
}
}
Future<void> main() async {
// Stream<int> --> Stream<String>
StreamTransformer<int, String> transformer =
StreamTransformer<int, String>.fromHandlers(
handleData: (int value, EventSink<String> es) {
es.add("String $value");
},
handleError: (Object error, StackTrace st, EventSink<String> es) {
es.add("String Value");
},
handleDone: (EventSink<String> es) {
es.add("Done!");
es.close(); // Optional
},
);
Stream<int> intStream = getIntStream();
Stream<String> wrappedStream = intStream.transform<String>(transformer);
await for (String value in wrappedStream) {
print(value);
}
}
Output:
String 0
String 1
String Value
String Value
String 4
Done!
- Dart StreamTransformer (***)
Các hướng dẫn lập trình Dart
- Kiểu dữ liệu Boolean trong Dart
- Hướng dẫn và ví dụ hàm trong Dart
- Hướng dẫn và ví dụ Dart Closures
- Interface trong Dart
- Hướng dẫn và ví dụ phương thức trong Dart
- Constructor trong Dart
- Property trong Dart
- Toán tử chấm chấm (..) trong Dart
- Hướng dẫn và ví dụ Dart Generics
- Lập trình Dart với công cụ trực tuyến DartPad
- Cài đặt Dart SDK trên Windows
- Cài đặt Visual Studio Code trên Windows
- Cài đặt Dart Code Extension cho Visual Studio Code
- Cài đặt Dart Plugin cho Android Studio
- Chạy ví dụ Dart đầu tiên của bạn trong Visual Studio Code
- Chạy ví dụ Dart đầu tiên của bạn trong Android Studio
- Hướng dẫn và ví dụ Dart Stream
- Dart JSON với thư viện dart:convert
- Hướng dẫn và ví dụ Dart List
- Biến (Variable) trong ngôn ngữ Dart
- Hướng dẫn và ví dụ Dart Map
- Vòng lặp trong Dart
- Xử lý Dart JSON với gói dart_json_mapper
- Trình chuyển đổi mã nguồn (Transpiler) là gì?
- Phân tích XML trong Dart
- Hướng dẫn và ví dụ Dart http
- Hướng dẫn và ví dụ Dart Future
- Các phương thức mở rộng (Extension) trong Dart
- Mixins trong Dart
- Bài thực hành Dart phân tích JSON với gói dart:convert
- Bài thực hành Dart http CRUD
- Từ khoá part và part of trong Dart
- Hướng dẫn và ví dụ Dart Dio
- So sánh đối tượng trong Dart với thư viện Equatable
- Xử lý lỗi trong Dart Stream
- Dart Stream Single và Broadcast
Show More