Salesforce Async Apex

什么是 Async Apex

在 Salesforce 中,Async Apex(异步 Apex) 是指在后台异步执行的 Apex 代码,不会阻塞用户的交互操作或当前事务。它适用于处理 大量数据、大计算量操作、或耗时任务

为什么使用 Async Apex

Salesforce 的同步 Apex 有很多限制(如 CPU 时间、SOQL 行数),当你需要执行以下操作时,异步 Apex 是更合适的选择:

  • 执行时间较长的逻辑处理
  • 处理大批量数据(避免同步时超时或超限)
  • 需要排队、定时、批次运行
  • 在事务提交后执行某些后续操作

Async Apex 的类型(4大类)

类型用途特点
Queueable Apex可排队执行的任务,逻辑清晰,可链式调用支持链式、上下文更灵活,推荐使用 ✅
Batch Apex批量处理大数据量记录可处理超出 governor limit 的大数据
Scheduled Apex定时执行任务(如每天凌晨3点发送报告)支持 Cron 表达式,周期性任务必选
Future Method最简单的异步方法,轻量级使用无法返回值、不支持链式、不推荐用于复杂逻辑

Queueable Apex

Queueable Apex 允许你将一个任务排入异步队列 (Flex Queue),由系统在稍后执行。

Queueable 接口

接口定义如下

public void execute(QueueableContext context);

方法说明:

  • execute:必须实现,它是执行异步逻辑的主方法
  • 参数 context:QueueableContext 提供上下文信息,如获取当前作业的 Job ID 例如在执行过程中输出当前 job 的 Id
public void execute(QueueableContext context) {
    Id jobId = context.getJobId();
    System.debug('Job ID: ' + jobId);
}

方法定义与调用

Salesforce 已经定义好 Queueable 接口,在定义 Queueable Apex 的时候,实际上是实现 Queueable 接口。

案例代码如下

public class MyQueueableJob implements Queueable {
    public void execute(QueueableContext context) {
        // 异步任务逻辑
        List<Account> accts = [SELECT Id, Name FROM Account LIMIT 10];
        for (Account a : accts) {
            a.Name += ' - Updated';
        }
        update accts;
    }
}

调用方法

ID jobId = System.enqueueJob(new MyQueueableJob());

链式调用案例

可以在一个 Queueable 任务中启动另一个,从而实现链式调用:

public class FirstJob implements Queueable {
    public void execute(QueueableContext context) {
        // 第一个任务逻辑
        System.debug('First job running...');

        // 链式启动第二个
        System.enqueueJob(new SecondJob());
    }
}

参数传递

Queueable 中默认是没有参数的,需要定义一个构造方法,实现有参构造。案例代码如下

public class SendEmailJob implements Queueable {
    List<Id> contactIds;

    public SendEmailJob(List<Id> contactIds) {
        this.contactIds = contactIds;
    }

    public void execute(QueueableContext context) {
        List<Contact> contacts = [SELECT Email FROM Contact WHERE Id IN :contactIds];
        // 发送邮件等操作
    }
}

该方法的调用方法调用 部分一致,只是在调用的时候需要传递相应参数。

Batch Apex

Batch Apex 是一种用于大数据量处理的异步 Apex 功能,允许你批量处理成千上万条记录,而不会触发平台的同步处理限制(例如 SOQL 查询行数或 DML 操作数的限制。

使用场景

Batch Apex 通常用于以下情况:

  • 处理超过 50,000 条记录(超出同步限制)
  • 大量数据清理或更新
  • 定期执行的数据任务(可以结合调度器)
  • 复杂的业务逻辑需要分段处理

Database.Batchable<SObject> 接口

public interface Database.Batchable<SObject> {
    Database.QueryLocator start(Database.BatchableContext bc);
    void execute(Database.BatchableContext bc, List<SObject> records);
    void finish(Database.BatchableContext bc);
}

Database.Batchable<SObject> 接口包含 三个必须实现的方法:

start(Database.BatchableContext context): 定义要处理的数据源,返回一个 Database.QueryLocator 或 Iterable<SObject>

  • 这是整个 Batch Job 的入口。
  • 返回的数据会被拆成一个个“批次”传给 execute()。
  • 使用 QueryLocator 时最多可处理 5000 万条记录。

execute(Database.BatchableContext context, List<SObject> scope): 对 start() 返回的数据进行处理。每个 scope 是一小批(比如 200 条)记录

  • 每批数据是一个事务,单独消耗 governor limit。
  • 每批默认最多 2000 条记录(调用 Database.executeBatch() 时设置)。

finish(Database.BatchableContext context): 当所有批次完成时调用一次。用于后处理,如:

  • 发送通知
  • 调用另一个 Batch 或 Queueable
  • 记录日志等

方法定义与调用

案例代码如下

global class UpdateContactStatusBatch implements Database.Batchable<SObject> {
    global Database.QueryLocator start(Database.BatchableContext BC) {
        return Database.getQueryLocator('SELECT Id, Status__c FROM Contact WHERE Status__c = null');
    }

    global void execute(Database.BatchableContext BC, List<SObject> scope) {
        for (Contact c : (List<Contact>)scope) {
            c.Status__c = 'New';
        }
        update scope;
    }

    global void finish(Database.BatchableContext BC) {
        System.debug('All contacts updated!');
    }
}

调用方法

UpdateContactStatusBatch batch = new UpdateContactStatusBatch();
Database.executeBatch(batch, 200); // 每批处理 200 条记录

Scheduled Apex

Scheduled Apex 允许你在 Salesforce 中定时运行 Apex 类(类似于定时任务、计划任务),适合用来执行周期性或延迟的后台操作,例如每日报告生成、每周数据清理等。

使用场景

Scheduled Apex 通常用于以下情况:

  • 定期清理旧数据:每周删除 90 天前未完成的记录
  • 定时发送提醒邮件: 每天早上 8 点向销售发送提醒
  • 定期同步外部系统: 每小时同步一次库存数据
  • 自动重新计算数据: 每天重新计算得分、预算等指标

Schedulable 接口

public interface Schedulable {
    void execute(SchedulableContext sc);
}

任何实现该接口的类必须实现 execute() 方法,这个方法是任务被调度时真正执行的内容。

方法定义与调用

案例代码如下

public class DailyContactUpdate implements Schedulable {
    public void execute(SchedulableContext context) {
        List<Contact> contacts = [SELECT Id, LastModifiedDate FROM Contact WHERE LastModifiedDate = LAST_N_DAYS:30];
        for (Contact c : contacts) {
            // 自定义处理逻辑
        }
    }
}

调用方法

System.schedule('Daily Contact Job', '0 0 7 * * ?', new DailyContactUpdate());

CRON 表达式格式

Seconds Minutes Hours Day_of_month Month Day_of_week Year (可选)

cron 示例如下:

表达式含义
0 0 0 * * ?每天凌晨 12 点
0 30 9 ? * MON-FRI每周一到五上午 9:30
0 0 12 1 * ?每月 1 日中午 12 点

管理 Scheduled Job

可以通过 SOQL 在salesforce中查看当前有哪些schedule job

SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger

或者通过设置页面查看,步骤: Setup > Scheduled Jobs

Future Method

Future Method 是一种异步执行机制,用于在后台延迟执行耗时或非关键操作(例如 HTTP 请求、发送邮件、大量更新等),从而避免当前事务被阻塞或触发 governor limits。

@future 是一个注解(Annotation),用于声明一个方法将在 未来的异步上下文中 被执行。

使用场景

  • 发送异步邮件: 避免触发器中执行 Messaging.sendEmail() 被 governor 限制
  • 调用外部接口: 使用 @future(callout=true) 进行远程 HTTP 请求
  • 更新大量记录: 延迟更新,规避触发器和 SOQL 限制
  • 日志记录或操作追踪: 在后台写入审计日志或历史表

语法

@future
public static void myFutureMethod(String someParam) {
    // 逻辑代码将在后台异步执行
}

也可以指定 callout=true 来支持 Web Service 调用:

@future(callout=true)
public static void callExternalService(String param) {
    // 支持 HTTP 请求等远程调用
}

方法定义与调用

示例代码1: 发送异步日志

public class Logger {
    @future
    public static void writeLog(String message) {
        Log__c log = new Log__c(Message__c = message);
        insert log;
    }
}

调用方法

Logger.writeLog('Record updated successfully');

示例代码2: 调用外部 HTTP 服务

public class ExternalApi {
    @future(callout=true)
    public static void callService(String param) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://api.example.com/data?query=' + param);
        req.setMethod('GET');

        Http http = new Http();
        HttpResponse res = http.send(req);
    }
}

使用限制

  • 方法必须是 static,实例方法不能使用 @future
  • 方法返回类型必须是,void 不支持返回任何值
  • 方法参数类型限制,只能是 primitive 类型(如 String、Integer、Id),不能是对象或自定义类
  • 每个事务最多调用 50 个 Future 方法
  • Future 方法 不能互相调用
  • 不支持在构造器、触发器递归中直接使用
  • 不适用于复杂链式操作(推荐用 Queueable 替代)

使用注意事项(Governor Limits)

虽然是异步执行,但 Async Apex 也有 限制

  • Queueable 每个作业最多排队 50 次
  • Batch Apex 单个批次最多返回 50 万条记录
  • Future 方法不能调用另一个 Future 方法或批处理
  • 所有异步操作总数也受 org 限制(异步 Apex 并非无限制)

Leave a Comment

Your email address will not be published. Required fields are marked *