In a Lightning Web Component, I'm making an API call to an Apex method, which can throw an exception. Currently, in the catch block, there's code checking for a specific string in the exception, b/c if it's a certain type of exception we want to display a certain message to the user; otherwise we want to display another generic message. Obviously determining the specific exception by string is not robust.
Is there a good way in JavaScript to determine which specific Apex exception was thrown?
I noticed that the error object that is currently being passed to the catch block does include a headers property, and I'm wondering if I could pass a custom value in there like exceptionType? Something like:
async myFunc() {
try {
const response = await myApexMethodCall();
} catch(err) {
if (err.headers.exceptionType === 'E123') {
alert('The order must be associated with a case before processing');
} else {
alert('There was an error with the API call. Please contact your administrator');
}
}
}
You can create a custom class which represents the response. For instance,
public with sharing class CustomOrderStatusResponse {
@AuraEnabled
public String errorCode { get; set; }
@AuraEnabled
public Map<String, String> result { get; set; }
public CustomOrderStatusResponse(String errorCode, Map<String, String> result) {
this.errorCode = errorCode;
this.result = result;
}
}
And, then in controller class, you can create instance of CustomOrderStatusResponse based on different scenarios and can set differnet values for errorCode. For instance,
public with sharing class CustomOrderStatus {
@AuraEnabled
public static CustomOrderStatusResponse getOrderStatus(String orderId){
CustomOrderStatusResponse response;
try {
if (orderId.equals('123')) {
Map<String, String> result = new Map<String, String>();
result.put('status', 'completed');
response = new CustomOrderStatusResponse(null, result);
} else if (orderId.equals('456')) {
response = new CustomOrderStatusResponse('E123', null);
} else if (orderId.equals('789')) {
response = new CustomOrderStatusResponse('E789', null);
}
return response;
} catch (Exception e) {
throw new AuraHandledException(e.getMessage());
}
}
}
In frontend (LWC), you can do something like this:
import { LightningElement } from 'lwc';
import getOrderStatus from "@salesforce/apex/CustomOrderStatus.getOrderStatus";
export default class OrderStatus extends LightningElement {
handleFirstClick(event) {
this.displayOrderStatus('123');
}
handleSecondClick(event) {
this.displayOrderStatus('456');
}
handleThirdClick(event) {
this.displayOrderStatus('789');
}
displayOrderStatus(orderId) {
getOrderStatus({ orderId: orderId })
.then(response => {
if (response.errorCode === 'E123') {
alert('The order must be associated with a case before processing');
} else if (response.errorCode) {
alert('There was an error with API Call');
} else {
alert('Status: ' + response.result.status);
}
})
.catch(console.error);
}
}
Reference: https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex_wire_method and https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex_call_imperative
I hope this answers your question. Any suggestions and comments are welcome.