JavaScript 高级错误处理实战示例

329

主题

193

回帖

2142

积分

管理员

积分
2142


JavaScript 高级错误处理实战示例

3.png


4.png




  1. /**
  2. * ============================================
  3. * JavaScript 高级错误处理实战示例
  4. * 演示企业级应用中的完整错误处理机制
  5. * 包含:自定义错误类、异步操作、数据验证、事务管理等
  6. * 交流QQ群: 711841924 (群一) / 528816639 (安卓内测群)
  7. * err
  8. * ============================================
  9. */

  10. // ==================== 自定义错误类定义 ====================

  11. // 基础应用错误类
  12. function AppError(message, code) {
  13.     this.name = "AppError";
  14.     this.message = message;
  15.     this.code = code || "UNKNOWN_ERROR";
  16.     this.timestamp = new Date().toISOString();
  17. }

  18. // 用户相关错误
  19. function UserError(message, code) {
  20.     this.name = "UserError";
  21.     this.message = message;
  22.     this.code = code || "USER_ERROR";
  23.     this.timestamp = new Date().toISOString();
  24. }

  25. // 数据库相关错误
  26. function DatabaseError(message, code) {
  27.     this.name = "DatabaseError";
  28.     this.message = message;
  29.     this.code = code || "DB_ERROR";
  30.     this.timestamp = new Date().toISOString();
  31. }

  32. // 业务逻辑错误
  33. function BusinessError(message, code) {
  34.     this.name = "BusinessError";
  35.     this.message = message;
  36.     this.code = code || "BUSINESS_ERROR";
  37.     this.timestamp = new Date().toISOString();
  38. }

  39. // 网络请求错误
  40. function NetworkError(message, code) {
  41.     this.name = "NetworkError";
  42.     this.message = message;
  43.     this.code = code || "NETWORK_ERROR";
  44.     this.timestamp = new Date().toISOString();
  45. }

  46. // ==================== 模拟数据存储 ====================

  47. var mockDatabase = {
  48.     users: [
  49.         { id: 1, username: "admin", email: "admin@example.com", role: "admin", status: "active" },
  50.         { id: 2, username: "user1", email: "user1@example.com", role: "user", status: "active" },
  51.         { id: 3, username: "user2", email: "user2@example.com", role: "user", status: "inactive" }
  52.     ],
  53.     products: [
  54.         { id: 101, name: "笔记本电脑", price: 5999, stock: 10, category: "electronics" },
  55.         { id: 102, name: "智能手机", price: 3999, stock: 50, category: "electronics" },
  56.         { id: 103, name: "办公椅", price: 899, stock: 25, category: "furniture" }
  57.     ],
  58.     orders: []
  59. };

  60. // ==================== 工具函数 ====================

  61. // 日志记录器
  62. function Logger(level, message, context) {
  63.     var timestamp = new Date().toISOString();
  64.     var logEntry = "[" + timestamp + "] [" + level + "] " + message;
  65.    
  66.     if (context) {
  67.         logEntry += " | Context: " + JSON.stringify(context);
  68.     }
  69.    
  70.     switch(level.toUpperCase()) {
  71.         case "ERROR":
  72.             printl("❌ " + logEntry);
  73.             break;
  74.         case "WARN":
  75.             printl("⚠️ " + logEntry);
  76.             break;
  77.         case "INFO":
  78.             printl("ℹ️ " + logEntry);
  79.             break;
  80.         case "DEBUG":
  81.             printl("🔍 " + logEntry);
  82.             break;
  83.         default:
  84.             printl(logEntry);
  85.     }
  86. }

  87. // 输入验证器
  88. function Validator() {
  89.     this.errors = [];
  90. }

  91. Validator.prototype.validateEmail = function(email) {
  92.     if (!email || typeof email !== 'string') {
  93.         throw new UserError("邮箱地址不能为空", "EMAIL_REQUIRED");
  94.     }
  95.    
  96.     if (email.indexOf('@') === -1 || email.indexOf('.') === -1) {
  97.         throw new UserError("邮箱格式不正确", "INVALID_EMAIL_FORMAT");
  98.     }
  99.    
  100.     return true;
  101. };

  102. Validator.prototype.validateUsername = function(username) {
  103.     if (!username || typeof username !== 'string') {
  104.         throw new UserError("用户名不能为空", "USERNAME_REQUIRED");
  105.     }
  106.    
  107.     if (username.length < 3 || username.length > 20) {
  108.         throw new UserError("用户名长度必须在3-20个字符之间", "INVALID_USERNAME_LENGTH");
  109.     }
  110.    
  111.     if (!/^[a-zA-Z0-9_]+$/.test(username)) {
  112.         throw new UserError("用户名只能包含字母、数字和下划线", "INVALID_USERNAME_CHARS");
  113.     }
  114.    
  115.     return true;
  116. };

  117. Validator.prototype.validatePassword = function(password) {
  118.     if (!password || typeof password !== 'string') {
  119.         throw new UserError("密码不能为空", "PASSWORD_REQUIRED");
  120.     }
  121.    
  122.     if (password.length < 6) {
  123.         throw new UserError("密码长度至少为6个字符", "PASSWORD_TOO_SHORT");
  124.     }
  125.    
  126.     if (!/[A-Z]/.test(password)) {
  127.         throw new UserError("密码必须包含至少一个大写字母", "PASSWORD_NO_UPPERCASE");
  128.     }
  129.    
  130.     if (!/[0-9]/.test(password)) {
  131.         throw new UserError("密码必须包含至少一个数字", "PASSWORD_NO_NUMBER");
  132.     }
  133.    
  134.     return true;
  135. };

  136. Validator.prototype.validateProductData = function(product) {
  137.     if (!product) {
  138.         throw new BusinessError("产品数据不能为空", "PRODUCT_DATA_REQUIRED");
  139.     }
  140.    
  141.     if (!product.name || product.name.trim() === "") {
  142.         throw new BusinessError("产品名称不能为空", "PRODUCT_NAME_REQUIRED");
  143.     }
  144.    
  145.     if (typeof product.price !== 'number' || product.price <= 0) {
  146.         throw new BusinessError("产品价格必须为正数", "INVALID_PRODUCT_PRICE");
  147.     }
  148.    
  149.     if (typeof product.stock !== 'number' || product.stock < 0) {
  150.         throw new BusinessError("产品库存不能为负数", "INVALID_PRODUCT_STOCK");
  151.     }
  152.    
  153.     return true;
  154. };

  155. // ==================== 核心业务函数 ====================

  156. // 用户注册功能(包含完整错误处理)
  157. function registerUser(userData) {
  158.     Logger("INFO", "开始用户注册流程", { username: userData.username });
  159.    
  160.     var result = { success: false, userId: null, message: "" };
  161.     var validator = new Validator();
  162.    
  163.     try {
  164.         // 步骤1: 验证输入数据
  165.         Logger("DEBUG", "执行输入验证");
  166.         validator.validateUsername(userData.username);
  167.         validator.validateEmail(userData.email);
  168.         validator.validatePassword(userData.password);
  169.         
  170.         Logger("INFO", "输入验证通过");
  171.         
  172.         // 步骤2: 检查用户是否已存在
  173.         Logger("DEBUG", "检查用户是否存在");
  174.         var existingUser = mockDatabase.users.find(function(u) {
  175.             return u.username === userData.username;
  176.         });
  177.         
  178.         if (existingUser) {
  179.             throw new UserError("用户名已存在", "USERNAME_EXISTS");
  180.         }
  181.         
  182.         // 步骤3: 创建新用户
  183.         Logger("DEBUG", "创建新用户记录");
  184.         var newUser = {
  185.             id: mockDatabase.users.length + 1,
  186.             username: userData.username,
  187.             email: userData.email,
  188.             role: "user",
  189.             status: "active",
  190.             createdAt: new Date().toISOString()
  191.         };
  192.         
  193.         mockDatabase.users.push(newUser);
  194.         
  195.         result.success = true;
  196.         result.userId = newUser.id;
  197.         result.message = "用户注册成功";
  198.         
  199.         Logger("INFO", "用户注册成功", { userId: newUser.id });
  200.         
  201.     } catch (error) {
  202.         Logger("err", "用户注册失败", { error: error.message, code: error.code });
  203.         
  204.         result.message = error.message;
  205.         result.errorCode = error.code;
  206.         
  207.         // 根据错误类型进行特殊处理
  208.         if (error instanceof UserError) {
  209.             Logger("WARN", "用户输入验证失败");
  210.         } else if (error instanceof BusinessError) {
  211.             Logger("WARN", "业务逻辑错误");
  212.         } else {
  213.             Logger("err", "未知系统错误");
  214.         }
  215.         
  216.     } finally {
  217.         Logger("DEBUG", "用户注册流程结束");
  218.     }
  219.    
  220.     return result;
  221. }

  222. // 订单处理功能(演示事务管理)
  223. function processOrder(orderData) {
  224.     Logger("INFO", "开始处理订单", { productId: orderData.productId, quantity: orderData.quantity });
  225.    
  226.     var result = { success: false, orderId: null, message: "" };
  227.     var transactionStarted = false;
  228.    
  229.     try {
  230.         // 步骤1: 验证订单数据
  231.         Logger("DEBUG", "验证订单数据");
  232.         if (!orderData.productId || !orderData.quantity) {
  233.             throw new BusinessError("订单数据不完整", "INCOMPLETE_ORDER_DATA");
  234.         }
  235.         
  236.         if (orderData.quantity <= 0) {
  237.             throw new BusinessError("订购数量必须大于0", "INVALID_QUANTITY");
  238.         }
  239.         
  240.         // 步骤2: 查找产品
  241.         Logger("DEBUG", "查找产品信息");
  242.         var product = mockDatabase.products.find(function(p) {
  243.             return p.id === orderData.productId;
  244.         });
  245.         
  246.         if (!product) {
  247.             throw new BusinessError("产品不存在", "PRODUCT_NOT_FOUND");
  248.         }
  249.         
  250.         // 步骤3: 检查库存
  251.         Logger("DEBUG", "检查产品库存");
  252.         if (product.stock < orderData.quantity) {
  253.             throw new BusinessError("库存不足,当前库存: " + product.stock, "INSUFFICIENT_STOCK");
  254.         }
  255.         
  256.         // 步骤4: 开始事务(模拟)
  257.         Logger("DEBUG", "开始订单事务");
  258.         transactionStarted = true;
  259.         
  260.         // 步骤5: 更新库存
  261.         Logger("DEBUG", "更新产品库存");
  262.         product.stock -= orderData.quantity;
  263.         
  264.         // 步骤6: 创建订单记录
  265.         Logger("DEBUG", "创建订单记录");
  266.         var newOrder = {
  267.             id: mockDatabase.orders.length + 1,
  268.             productId: orderData.productId,
  269.             productName: product.name,
  270.             quantity: orderData.quantity,
  271.             totalPrice: product.price * orderData.quantity,
  272.             status: "confirmed",
  273.             createdAt: new Date().toISOString()
  274.         };
  275.         
  276.         mockDatabase.orders.push(newOrder);
  277.         
  278.         // 步骤7: 提交事务
  279.         Logger("DEBUG", "提交订单事务");
  280.         transactionStarted = false;
  281.         
  282.         result.success = true;
  283.         result.orderId = newOrder.id;
  284.         result.message = "订单处理成功";
  285.         
  286.         Logger("INFO", "订单处理成功", { orderId: newOrder.id, total: newOrder.totalPrice });
  287.         
  288.     } catch (error) {
  289.         Logger("err", "订单处理失败", { error: error.message, code: error.code });
  290.         
  291.         result.message = error.message;
  292.         result.errorCode = error.code;
  293.         
  294.         // 如果事务已开始,则回滚
  295.         if (transactionStarted) {
  296.             Logger("WARN", "执行事务回滚");
  297.             // 在实际应用中这里会恢复库存等状态
  298.             transactionStarted = false;
  299.         }
  300.         
  301.     } finally {
  302.         Logger("DEBUG", "订单处理流程结束");
  303.     }
  304.    
  305.     return result;
  306. }

  307. // 数据查询功能(演示多种查询场景)
  308. function queryData(queryType, filters) {
  309.     Logger("INFO", "执行数据查询", { type: queryType, filters: filters });
  310.    
  311.     var result = { success: false, data: [], count: 0, message: "" };
  312.    
  313.     try {
  314.         // 参数验证
  315.         if (!queryType) {
  316.             throw new AppError("查询类型不能为空", "QUERY_TYPE_REQUIRED");
  317.         }
  318.         
  319.         switch (queryType.toLowerCase()) {
  320.             case "users":
  321.                 Logger("DEBUG", "查询用户数据");
  322.                
  323.                 if (filters && filters.role) {
  324.                     result.data = mockDatabase.users.filter(function(u) {
  325.                         return u.role === filters.role;
  326.                     });
  327.                 } else {
  328.                     result.data = mockDatabase.users.slice(); // 返回副本
  329.                 }
  330.                 break;
  331.                
  332.             case "products":
  333.                 Logger("DEBUG", "查询产品数据");
  334.                
  335.                 if (filters && filters.category) {
  336.                     result.data = mockDatabase.products.filter(function(p) {
  337.                         return p.category === filters.category;
  338.                     });
  339.                 } else if (filters && filters.minPrice) {
  340.                     result.data = mockDatabase.products.filter(function(p) {
  341.                         return p.price >= filters.minPrice;
  342.                     });
  343.                 } else {
  344.                     result.data = mockDatabase.products.slice();
  345.                 }
  346.                 break;
  347.                
  348.             case "orders":
  349.                 Logger("DEBUG", "查询订单数据");
  350.                
  351.                 if (filters && filters.status) {
  352.                     result.data = mockDatabase.orders.filter(function(o) {
  353.                         return o.status === filters.status;
  354.                     });
  355.                 } else {
  356.                     result.data = mockDatabase.orders.slice();
  357.                 }
  358.                 break;
  359.                
  360.             default:
  361.                 throw new AppError("不支持的查询类型: " + queryType, "UNSUPPORTED_QUERY_TYPE");
  362.         }
  363.         
  364.         result.count = result.data.length;
  365.         result.success = true;
  366.         result.message = "查询成功,返回 " + result.count + " 条记录";
  367.         
  368.         Logger("INFO", "数据查询成功", { count: result.count });
  369.         
  370.     } catch (error) {
  371.         Logger("err", "数据查询失败", { error: error.message, code: error.code });
  372.         
  373.         result.message = error.message;
  374.         result.errorCode = error.code;
  375.         
  376.     } finally {
  377.         Logger("DEBUG", "数据查询流程结束");
  378.     }
  379.    
  380.     return result;
  381. }

  382. // 批量操作功能(演示复杂的错误处理)
  383. function batchProcess(items, operation) {
  384.     Logger("INFO", "开始批量操作", { itemCount: items.length, operation: operation });
  385.    
  386.     var results = {
  387.         successful: [],
  388.         failed: [],
  389.         summary: {}
  390.     };
  391.    
  392.     try {
  393.         for (var i = 0; i < items.length; i++) {
  394.             var item = items[i];
  395.             var itemResult = { index: i, item: item, success: false, error: null };
  396.             
  397.             try {
  398.                 // 对每个项目执行操作
  399.                 switch (operation) {
  400.                     case "validate":
  401.                         // 验证操作
  402.                         if (!item || typeof item !== 'object') {
  403.                             throw new AppError("无效的项目数据", "INVALID_ITEM");
  404.                         }
  405.                         itemResult.success = true;
  406.                         break;
  407.                         
  408.                     case "transform":
  409.                         // 转换操作
  410.                         if (!item.name) {
  411.                             throw new AppError("项目缺少名称字段", "MISSING_NAME_FIELD");
  412.                         }
  413.                         item.transformed = item.name.toUpperCase();
  414.                         itemResult.success = true;
  415.                         break;
  416.                         
  417.                     case "process":
  418.                         // 处理操作(模拟)
  419.                         if (Math.random() > 0.8) { // 20%概率失败
  420.                             throw new AppError("随机处理失败", "RANDOM_FAILURE");
  421.                         }
  422.                         itemResult.success = true;
  423.                         break;
  424.                         
  425.                     default:
  426.                         throw new AppError("不支持的操作类型: " + operation, "UNSUPPORTED_OPERATION");
  427.                 }
  428.                
  429.                 results.successful.push(itemResult);
  430.                
  431.             } catch (itemError) {
  432.                 Logger("WARN", "批量操作中单个项目失败", {
  433.                     index: i,
  434.                     error: itemError.message
  435.                 });
  436.                
  437.                 itemResult.error = itemError.message;
  438.                 results.failed.push(itemResult);
  439.             }
  440.         }
  441.         
  442.         // 生成摘要
  443.         results.summary = {
  444.             total: items.length,
  445.             successful: results.successful.length,
  446.             failed: results.failed.length,
  447.             successRate: Math.round((results.successful.length / items.length) * 100) + "%"
  448.         };
  449.         
  450.         Logger("INFO", "批量操作完成", results.summary);
  451.         
  452.     } catch (batchError) {
  453.         Logger("err", "批量操作整体失败", { error: batchError.message });
  454.         throw batchError; // 重新抛出严重错误
  455.         
  456.     } finally {
  457.         Logger("DEBUG", "批量操作流程结束");
  458.     }
  459.    
  460.     return results;
  461. }

  462. // ==================== 测试用例 ====================

  463. function runTests() {
  464.     Logger("INFO", "========== 开始运行测试用例 ==========");
  465.    
  466.     // 测试1: 成功的用户注册
  467.     Logger("INFO", "--- 测试1: 成功用户注册 ---");
  468.     var testUser1 = {
  469.         username: "newuser1",
  470.         email: "newuser1@example.com",
  471.         password: "Password123"
  472.     };
  473.     var regResult1 = registerUser(testUser1);
  474.     printl("测试结果: " + (regResult1.success ? "✅ 通过" : "❌ 失败"));
  475.     sleep.second(2);
  476.    
  477.     // 测试2: 失败的用户注册(用户名太短)
  478.     Logger("INFO", "--- 测试2: 用户名太短 ---");
  479.     var testUser2 = {
  480.         username: "ab",
  481.         email: "short@example.com",
  482.         password: "Password123"
  483.     };
  484.     var regResult2 = registerUser(testUser2);
  485.     printl("测试结果: " + (!regResult2.success ? "✅ 通过" : "❌ 失败"));
  486.     sleep.second(2);
  487.    
  488.     // 测试3: 失败的用户注册(邮箱格式错误)
  489.     Logger("INFO", "--- 测试3: 邮箱格式错误 ---");
  490.     var testUser3 = {
  491.         username: "validuser",
  492.         email: "invalid-email",
  493.         password: "Password123"
  494.     };
  495.     var regResult3 = registerUser(testUser3);
  496.     printl("测试结果: " + (!regResult3.success ? "✅ 通过" : "❌ 失败"));
  497.     sleep.second(2);
  498.    
  499.     // 测试4: 成功的订单处理
  500.     Logger("INFO", "--- 测试4: 成功订单处理 ---");
  501.     var testOrder1 = {
  502.         productId: 101,
  503.         quantity: 2
  504.     };
  505.     var orderResult1 = processOrder(testOrder1);
  506.     printl("测试结果: " + (orderResult1.success ? "✅ 通过" : "❌ 失败"));
  507.     sleep.second(2);
  508.    
  509.     // 测试5: 失败的订单处理(库存不足)
  510.     Logger("INFO", "--- 测试5: 库存不足 ---");
  511.     var testOrder2 = {
  512.         productId: 101,
  513.         quantity: 100  // 超过库存
  514.     };
  515.     var orderResult2 = processOrder(testOrder2);
  516.     printl("测试结果: " + (!orderResult2.success ? "✅ 通过" : "❌ 失败"));
  517.     sleep.second(2);
  518.    
  519.     // 测试6: 数据查询
  520.     Logger("INFO", "--- 测试6: 查询活跃用户 ---");
  521.     var queryResult1 = queryData("users", { role: "user" });
  522.     printl("查询结果: " + (queryResult1.success ? "✅ 通过" : "❌ 失败") +
  523.            ", 找到 " + queryResult1.count + " 条记录");
  524.     sleep.second(2);
  525.    
  526.     // 测试7: 批量处理
  527.     Logger("INFO", "--- 测试7: 批量验证操作 ---");
  528.     var batchItems = [
  529.         { name: "Item1", value: 100 },
  530.         { name: "Item2", value: 200 },
  531.         { invalid: true },  // 无效项
  532.         { name: "Item3", value: 300 }
  533.     ];
  534.     var batchResult = batchProcess(batchItems, "validate");
  535.     printl("批量处理结果: 成功 " + batchResult.summary.successful +
  536.            " 个, 失败 " + batchResult.summary.failed + " 个");
  537.     sleep.second(2);
  538.    
  539.     Logger("INFO", "========== 测试用例执行完毕 ==========");
  540. }

  541. // ==================== 主程序入口 ====================

  542. function main() {
  543.     Logger("INFO", "========================================");
  544.     Logger("INFO", "   JavaScript 高级错误处理实战示例     ");
  545.     Logger("INFO", "========================================");
  546.    
  547.     try {
  548.         // 运行所有测试
  549.         runTests();
  550.         
  551.         // 显示最终统计
  552.         Logger("INFO", "========================================");
  553.         Logger("INFO", "           执行总结");
  554.         Logger("INFO", "========================================");
  555.         Logger("INFO", "总用户数: " + mockDatabase.users.length);
  556.         Logger("INFO", "总产品数: " + mockDatabase.products.length);
  557.         Logger("INFO", "总订单数: " + mockDatabase.orders.length);
  558.         Logger("INFO", "✅ 示例程序执行完成");
  559.         
  560.     } catch (criticalError) {
  561.         Logger("err", "程序发生严重错误", {
  562.             error: criticalError.message,
  563.             stack: criticalError.stack || "无堆栈信息"
  564.         });
  565.         
  566.     } finally {
  567.         Logger("INFO", "========================================");
  568.         Logger("INFO", "         程序执行结束");
  569.         Logger("INFO", "========================================");
  570.         printl("===== JavaScript 高级错误处理实战示例结束 =====");
  571.         printl("========== 脚本执行完毕 ==========");
  572.     }
  573. }

  574. // 启动主程序
  575. main();
复制代码


举报 回复