Flutter安全结果处理插件safe_result的使用
Flutter 安全结果处理插件 safe_result 的使用
safe_result
是一个 Dart 包,它提供了一种类型安全的方式来处理成功和错误情况,并支持自定义错误类型。
特性
- 类型安全的错误处理,支持自定义错误类型
- 支持模式匹配
- 功能编程工具
- 支持异步操作
- 支持空安全
- 支持泛型错误类型,以提高错误处理能力
开始使用
在 pubspec.yaml
文件中添加依赖:
dependencies:
safe_result: ^2.0.1
使用示例
基本用法
import 'package:safe_result/safe_result.dart';
// 定义自定义错误类型
sealed class AppError {
final String message;
const AppError(this.message);
@override
String toString() => message;
}
class ValidationError extends AppError {
const ValidationError(super.message);
}
class NetworkError extends AppError {
final int statusCode;
const NetworkError(super.message, this.statusCode);
@override
String toString() => '$message (Status: $statusCode)';
}
void main() {
// 创建带有特定错误类型的 Result 对象
final success = Result<int, ValidationError>.ok(42);
final failure = Result<int, ValidationError>.error(
ValidationError('Value must be positive'));
// 检查结果类型
print('Is success? ${success.isOk}'); // true
print('Is failure? ${failure.isError}'); // true
// 获取值
final value = success.getOrElse(0);
print('Value or default: $value'); // 42
final fallback = failure.getOrElse(0);
print('Fallback value: $fallback'); // 0
}
模式匹配
// 使用 switch 表达式进行模式匹配
Result<String, ValidationError> processInput(String input) => switch (input) {
'' => Result.error(ValidationError('Input cannot be empty')),
var str when str.length < 3 =>
Result.error(ValidationError('Input too short')),
var str => Result.ok(str.toUpperCase())
};
// 使用 switch 语句处理结果
void handleResult(Result<String, ValidationError> result) {
switch (result) {
case Ok(value: final v):
print('Success: $v');
case Error(error: final e):
print('Error: $e');
}
}
handleResult(processInput('')); // Error: Input cannot be empty
handleResult(processInput('hi')); // Error: Input too short
handleResult(processInput('hello')); // Success: HELLO
变换
final result = Result<int, ValidationError>.ok(42);
// 使用 map 方法对成功值进行变换
final doubled = result.map((value) => value * 2);
print(doubled); // Ok(84)
// 使用 fold 方法对值和错误类型进行变换
final networkResult = result.fold<String, NetworkError>(
onOk: (value) => Result.ok('Success: $value'),
onError: (error) => Result.error(NetworkError(error.toString(), 400)),
);
print(networkResult); // Ok(Success: 42)
// 处理错误情况
final failedResult = Result<int, ValidationError>.error(
ValidationError('Invalid input'),
);
final transformedError = failedResult.fold<String, NetworkError>(
onOk: (value) => Result.ok('Success: $value'),
onError: (error) => Result.error(NetworkError(error.toString(), 400)),
);
print(transformedError); // Error: Invalid input (Status: 400)
// 使用不同错误类型的链式变换
final dbResult = result.map((value) => value * 2).fold<String, DatabaseError>(
onOk: (value) => value > 50
? Result.ok('Large number: $value')
: Result.error(DatabaseError('Number too small')),
onError: (error) => Result.error(DatabaseError(error.toString())),
);
print(dbResult); // Ok(Large number: 84)
验证
class User {
final String name;
final int age;
final String email;
User(this.name, this.age, this.email);
@override
String toString() => 'User(name: $name, age: $age, email: $email)';
}
// 验证函数返回带有 ValidationError 的 Result
Result<String, ValidationError> validateName(String name) {
if (name.isEmpty) {
return Result.error(ValidationError('Name cannot be empty'));
}
if (name.length < 2) {
return Result.error(ValidationError('Name too short'));
}
return Result.ok(name);
}
Result<int, ValidationError> validateAge(int age) {
if (age < 0 || age > 120) {
return Result.error(ValidationError('Invalid age'));
}
return Result.ok(age);
}
Result<String, ValidationError> validateEmail(String email) {
final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
if (!emailRegex.hasMatch(email)) {
return Result.error(ValidationError('Invalid email format'));
}
return Result.ok(email);
}
// 结合多个验证
Result<User, ValidationError> createUser(String name, int age, String email) {
final nameResult = validateName(name);
final ageResult = validateAge(age);
final emailResult = validateEmail(email);
return switch ((nameResult, ageResult, emailResult)) {
(Ok(value: final n), Ok(value: final a), Ok(value: final e)) =>
Result.ok(User(n, a, e)),
(Error(error: final e), _, _) => Result.error(e),
(_, Error(error: final e), _) => Result.error(e),
(_, _, Error(error: final e)) => Result.error(e),
};
}
// 示例用法
final validUser = createUser('John', 30, 'john@example.com');
final invalidUser = createUser('', -5, 'invalid-email');
print(validUser); // Ok(User(name: John, age: 30, email: john@example.com))
print(invalidUser); // Error: Name cannot be empty
异步操作
Future<void> asyncExample() async {
// 模拟异步操作并返回带有 NetworkError 的 Result
Future<Result<String, NetworkError>> fetchUserName() async {
try {
// 模拟 API 调用
await Future.delayed(Duration(seconds: 1));
return Result.ok('John Doe');
} catch (e) {
return Result.error(NetworkError('Failed to fetch user', 500));
}
}
Future<Result<int, NetworkError>> fetchUserAge(String userName) async {
try {
// 模拟 API 调用
await Future.delayed(Duration(seconds: 1));
return Result.ok(30);
} catch (e) {
return Result.error(NetworkError('Failed to fetch age', 404));
}
}
// 使用 andThen 进行链式异步操作
final result = await fetchUserName().andThen((name) => fetchUserAge(name));
// 处理最终结果
switch (result) {
case Ok(value: final age):
print('User age: $age');
case Error(error: final e):
print('Error: $e');
}
}
错误处理最佳实践
-
定义领域特定的错误类型
sealed class ApiError extends AppError { ... } sealed class DomainError extends AppError { ... } sealed class ValidationError extends AppError { ... }
-
使用错误类型的模式匹配
switch (result) { case Error(error: NetworkError e) when e.statusCode == 404: print('Resource not found: ${e.message}'); case Error(error: ValidationError e): print('Validation failed: ${e.message}'); case Ok(value: final v): print('Success: $v'); }
-
链式操作保持一致的错误类型
Result<T, E> validateAndTransform<T, E extends AppError>(T input) { return validate(input) .map(transform) .fold( onOk: (value) => Result.ok(value), onError: (error) => Result.error(error), ); }
更多关于Flutter安全结果处理插件safe_result的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复