safe_call.dart
2.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import '../constants/network_const.dart';
import '../error/app_error.dart';
import '../error/app_error_handler.dart';
import '../error/http_error_handling_policy.dart';
import '../error/http_server_custom_error.dart';
import 'app_result.dart';
/// Wraps async work into [AppResult] with optional global error handling.
///
/// Pass a non-null [errorHandlingPolicy] to enable global side effects (toast,
/// logout). Pass null (or omit) for silent mode — caller handles errors itself.
Future<AppResult<T>> safeCall<T>({
required Future<T> Function() call,
HttpErrorHandlingPolicy? errorHandlingPolicy =
HttpErrorHandlingPolicy.defaultPolicy,
}) async {
try {
final data = await call();
return AppSuccess(data);
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) {
return const AppFailure(AppCancelledError());
}
final error = _mapDioException(e);
if (errorHandlingPolicy != null) {
Get.find<AppErrorHandler>().handle(error, policy: errorHandlingPolicy);
}
return AppFailure(error);
} on AppCancelledError catch (e) {
return AppFailure(e);
} catch (e) {
final error = AppUnknownError(e);
if (errorHandlingPolicy != null) {
Get.find<AppErrorHandler>().handle(error, policy: errorHandlingPolicy);
}
return AppFailure(error);
}
}
AppError _mapDioException(DioException e) {
final response = e.response;
if (response == null) {
return AppNetworkError(e);
}
HttpServerCustomError? serverError;
final body = response.data;
if (body is Map<String, dynamic>) {
serverError = HttpServerCustomError.fromJson(body);
} else if (body is String && body.isNotEmpty) {
try {
final map = jsonDecode(body) as Map<String, dynamic>;
serverError = HttpServerCustomError.fromJson(map);
} catch (_) {
serverError = null;
}
}
final token = response.requestOptions.headers[NetworkConst.headerAccessToken]?.toString();
return AppHttpError(
statusCode: response.statusCode,
customError: serverError,
accessToken: token,
cause: e,
);
}