LWC场景下如何在JavaScript Try/Catch中区分Apex API异常类型
LWC调用Apex时可靠识别异常类型的实现方案
你提到的通过headers传入自定义exceptionType判断异常类型的方案是可行的,除此之外还有两种常用的稳定方案,均可以完全避免匹配异常字符串的不稳定问题。
方案1:结构化错误信息 + AuraHandledException
这是Salesforce官方推荐的常规方案,将异常类型和提示信息封装为JSON字符串放在AuraHandledException的消息中,前端捕获后解析即可。
Apex示例代码
public class OrderService { @AuraEnabled(cacheable=false) public static String processOrder(Id orderId) { try { // 业务逻辑校验 if([SELECT Count() FROM Case WHERE OrderId = :orderId] == 0) { Map<String, Object> errMap = new Map<String, Object>{ 'exceptionType' => 'E123', 'message' => '处理前订单必须关联对应的工单' }; throw new AuraHandledException(JSON.serialize(errMap)); } // 其他业务逻辑 return '处理成功'; } catch(Exception e) { if(e instanceof AuraHandledException) { throw e; } // 未知异常返回通用结构 Map<String, Object> errMap = new Map<String, Object>{ 'exceptionType' => 'E999', 'message' => '系统内部错误' }; throw new AuraHandledException(JSON.serialize(errMap)); } } }
LWC前端示例代码
async myFunc() { try { const response = await myApexMethodCall(); // 成功逻辑处理 } catch(err) { try { // 解析结构化异常信息 const errInfo = JSON.parse(err.body.message); if (errInfo.exceptionType === 'E123') { alert(errInfo.message); } else { alert('接口调用出错,请联系系统管理员'); } } catch(parseErr) { // 兼容非结构化异常的兜底处理 alert('接口调用出错,请联系系统管理员'); } } }
方案2:自定义响应头传递异常类型(你提到的方案)
该方案直接把异常类型放在响应头中返回,前端无需解析JSON,直接读取头字段即可,注意仅支持cacheable=false的Apex方法,开启缓存的方法无法返回自定义响应头。
Apex示例代码
@AuraEnabled(cacheable=false) public static String processOrder(Id orderId) { if([SELECT Count() FROM Case WHERE OrderId = :orderId] == 0) { // 写入自定义响应头 ApexPages.currentPage().getHeaders().put('exceptionType', 'E123'); throw new AuraHandledException('处理前订单必须关联对应的工单'); } return '处理成功'; }
LWC前端示例代码
和你给出的代码逻辑完全一致:
async myFunc() { try { const response = await myApexMethodCall(); } catch(err) { if (err.headers.exceptionType === 'E123') { alert('处理前订单必须关联对应的工单'); } else { alert('接口调用出错,请联系系统管理员'); } } }
方案3:统一响应结构体(无异常抛出)
该方案是稳定性最高的方案,Apex侧不抛出任何异常,而是返回固定格式的响应对象,前端通过返回的状态码判断业务结果,同时支持开启缓存的Apex方法。
Apex示例代码
// 统一响应结构体 public class ApiResponse { @AuraEnabled public Integer code; // 0=成功,其他值为错误码 @AuraEnabled public String message; @AuraEnabled public Object data; } @AuraEnabled(cacheable=true) public static ApiResponse processOrder(Id orderId) { ApiResponse res = new ApiResponse(); try { if([SELECT Count() FROM Case WHERE OrderId = :orderId] == 0) { res.code = 123; res.message = '处理前订单必须关联对应的工单'; return res; } res.code = 0; res.data = '处理成功'; return res; } catch(Exception e) { res.code = 999; res.message = '系统内部错误'; return res; } }
LWC前端示例代码
async myFunc() { const res = await myApexMethodCall(); if(res.code === 0) { // 成功逻辑处理 console.log(res.data); } else if(res.code === 123) { alert(res.message); } else { alert('接口调用出错,请联系系统管理员'); } }
选型建议
- 若Apex方法需要开启缓存,优先选择方案3
- 若不需要开启缓存,方案1和方案2均可按需选择,方案1兼容性更强,不需要依赖响应头
内容的提问来源于stack exchange,提问作者jbyrd
相关产品推荐
相关产品推荐

