handlers.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import type { Method } from "alova";
  2. import router from "@/router";
  3. // Custom error class for API errors
  4. export class ApiError extends Error {
  5. code: number;
  6. data?: any;
  7. constructor(message: string, code: number, data?: any) {
  8. super(message);
  9. this.name = "ApiError";
  10. this.code = code;
  11. this.data = data;
  12. }
  13. }
  14. // Define a type for the expected API response structure
  15. interface ApiResponse {
  16. code?: number;
  17. message?: string;
  18. result?: any;
  19. success?: boolean;
  20. total?: number;
  21. more?: boolean;
  22. }
  23. // Handle successful responses
  24. export async function handleAlovaResponse(
  25. response:
  26. | UniApp.RequestSuccessCallbackResult
  27. | UniApp.UploadFileSuccessCallbackResult
  28. | UniApp.DownloadSuccessData,
  29. ) {
  30. return new Promise((resolve, reject) => {
  31. const globalToast = useGlobalToast();
  32. // Extract status code and data from UniApp response
  33. const { statusCode, data } =
  34. response as UniNamespace.RequestSuccessCallbackResult;
  35. // 处理401/403错误(如果不是在handleAlovaResponse中处理的)
  36. if (
  37. typeof data === "object" &&
  38. data !== null &&
  39. "code" in data &&
  40. (data.code === 401 || data.code === 403)
  41. ) {
  42. // 如果是未授权错误,清除用户信息并跳转到登录页
  43. uni.showToast({
  44. title: "登录已过期,请重新登录!",
  45. duration: 2000,
  46. icon: "none",
  47. });
  48. const timer = setTimeout(() => {
  49. clearTimeout(timer);
  50. router.replaceAll({ name: "login" });
  51. }, 500);
  52. throw new ApiError("登录已过期,请重新登录!", statusCode, data);
  53. }
  54. // Handle HTTP error status codes
  55. if (
  56. typeof data === "object" &&
  57. data !== null &&
  58. "code" in data &&
  59. data.code >= 400
  60. ) {
  61. uni.showToast({
  62. title: (data as any).message,
  63. duration: 2000,
  64. icon: "none",
  65. });
  66. reject(`${(data as any).message}`);
  67. }
  68. // The data is already parsed by UniApp adapter
  69. const json = data as ApiResponse;
  70. // Log response in development
  71. if (import.meta.env.MODE === "development") {
  72. console.log("[Alova Response]", json);
  73. }
  74. // Return data for successful responses
  75. resolve(json.result);
  76. });
  77. }
  78. // Handle request errors
  79. export function handleAlovaError(error: any, method: Method) {
  80. const globalToast = useGlobalToast();
  81. // Log error in development
  82. if (import.meta.env.MODE === "development") {
  83. console.error("[Alova Error]", error, method);
  84. }
  85. if (error.name === "Error") {
  86. uni.showToast({
  87. title: "服务器异常,请稍后再试",
  88. icon: "none",
  89. });
  90. }
  91. // 处理401/403错误(如果不是在handleAlovaResponse中处理的)
  92. if (error instanceof ApiError && (error.code === 401 || error.code === 403)) {
  93. // 如果是未授权错误,清除用户信息并跳转到登录页
  94. globalToast.error({ msg: "登录已过期,请重新登录!", duration: 500 });
  95. const timer = setTimeout(() => {
  96. clearTimeout(timer);
  97. router.replaceAll({ name: "login" });
  98. }, 500);
  99. throw new ApiError("登录已过期,请重新登录!", error.code, error.data);
  100. }
  101. // Handle different types of errors
  102. if (error.name === "NetworkError") {
  103. globalToast.error("网络错误,请检查您的网络连接");
  104. } else if (error.name === "TimeoutError") {
  105. globalToast.error("请求超时,请重试");
  106. } else if (error instanceof ApiError) {
  107. globalToast.error(error.message || "请求失败");
  108. } else {
  109. globalToast.error("发生意外错误");
  110. }
  111. throw error;
  112. }