Skip to main content
This component demonstrates how to call an Apex method imperatively using JavaScript’s async/await pattern. Unlike @wire, imperative calls are triggered by user actions or component logic.

Implementation

import { LightningElement } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';

export default class ApexImperativeMethod extends LightningElement {
    contacts;
    error;

    async handleLoad() {
        try {
            this.contacts = await getContactList();
            this.error = undefined;
        } catch (error) {
            this.contacts = undefined;
            this.error = error;
        }
    }
}

Key Features

Imperative Call

Import and call the Apex method as a JavaScript function:
import getContactList from '@salesforce/apex/ContactController.getContactList';

// Call it imperatively
this.contacts = await getContactList();

Async/Await Pattern

Use async/await for cleaner asynchronous code:
async handleLoad() {
    try {
        this.contacts = await getContactList();
        this.error = undefined;
    } catch (error) {
        this.contacts = undefined;
        this.error = error;
    }
}

Error Handling

Use try/catch to handle errors:
try {
    this.contacts = await getContactList();
    this.error = undefined; // Clear previous errors
} catch (error) {
    this.contacts = undefined; // Clear previous data
    this.error = error;
}

User-Triggered Execution

The method is called when the user clicks the button:
<lightning-button
    label="Load Contacts"
    onclick={handleLoad}
></lightning-button>

Properties

PropertyTypeDescription
contactsArrayList of contacts returned from Apex
errorObjectError object if the call fails

Apex Method Requirements

For cacheable methods (read-only operations):
@AuraEnabled(cacheable=true)
public static List<Contact> getContactList() {
    // Method implementation
}
For non-cacheable methods (DML operations):
@AuraEnabled
public static void updateContact(Contact contact) {
    // Method implementation
}

Error Types

Common error scenarios:
  1. No access: User lacks permission to access records
  2. SOQL errors: Invalid query or limits exceeded
  3. DML errors: Failed insert/update/delete operations
  4. Custom errors: Thrown by your Apex code

When to Use Imperative vs Wire

Use Imperative When:

  • You need to call the method in response to user actions
  • You want control over when the method executes
  • You need to perform DML operations
  • You want to chain multiple operations
  • You need to pass dynamic parameters

Use Wire When:

  • Data should load automatically
  • You want reactive updates
  • You’re doing read-only operations
  • Parameters are reactive properties

Best Practices

  1. Always use try/catch: Handle errors gracefully
  2. Clear previous state: Reset data or error on each call
  3. Use async/await: Cleaner than promise chains
  4. Show loading state: Indicate when operation is in progress
  5. Handle all error cases: Provide meaningful error messages

Advanced Example with Loading State

async handleLoad() {
    this.isLoading = true;
    try {
        this.contacts = await getContactList();
        this.error = undefined;
    } catch (error) {
        this.contacts = undefined;
        this.error = error;
    } finally {
        this.isLoading = false;
    }
}

Comparison with Wire

FeatureImperativeWire
ExecutionOn-demandAutomatic
ControlManualAutomatic
CachingOptionalRequired for cacheable
DML operationsSupportedNot supported
User actionRequiredNot required
ReactivityManualAutomatic

Build docs developers (and LLMs) love