-1

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');
        }
    }
}
jbyrd
  • 5,287
  • 7
  • 52
  • 86

1 Answers1

1

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.