Skip to main content
Join the Agentforce Hackathon on Nov. 18-19 to compete for a $20,000 Grand Prize. Sign up now. Terms apply.

Verwenden von asynchronem Apex

Lernziele

Nachdem Sie diese Lektion abgeschlossen haben, sind Sie in der Lage, die folgenden Aufgaben auszuführen:

  • Erläutern, wann asynchroner Apex zu verwenden ist
  • Verwenden von Future-Methoden zur Handhabung von Web-Callouts
  • Arbeiten mit der "Batchable"-Schnittstelle zur Verarbeitung einer großen Zahl von Datensätzen
  • Erläutern der Vorteile, die die Verwendung der Queueable-Schnittstelle bietet, wenn Sie sich in der Mitte treffen müssen

Mit Trail Together einem Dozenten folgen

Möchten Sie bei diesem Schritt einem Experten folgen? Schauen Sie sich dieses Video an, das Teil der Reihe "Trail Together" ist.

(Dieser Clip beginnt bei Minute 32:07, für den Fall, dass Sie zurückspringen und den Anfang des Schritts noch einmal sehen möchten.)

Der richtige Zeitpunkt, um asynchron vorzugehen

Als .NET-Entwickler haben Sie bestimmt schon einmal Bekanntschaft mit der Welt des asynchronen Programmierens gemacht. Gehen wir einmal davon aus, dass Sie wissen, worum es sich dabei handelt, und die Vorteile kennen, die mit der Nutzung dieses Programmiermodells verbunden sind. Was Sie vielleicht nicht wissen, ist, wann Sie asynchrones Programmieren auf der Lightning-Plattform nutzen sollten.

In der Regel basiert die Wahl des asynchronen Programmierens auf den folgenden drei Gründen.

  • Verarbeitung einer großen Zahl von Datensätzen. Dieser Grund spielt nur in der mandantenfähigen Welt der Lightning-Plattform eine Rolle, in der es feste Grenzen gibt. Die mit asynchronen Prozessen verbundenen Grenzen sind höher gesteckt als es bei synchronen Prozessen der Fall ist. Daher ist die asynchrone Verarbeitung die beste Wahl, wenn Sie Tausende oder gar Millionen von Datensätzen verarbeiten müssen.
  • Vornehmen von Callouts bei externen Webservices. Bei Callouts kann es lange dauern, sie zu verarbeiten, aber in der Lightning-Plattform können Auslöser Callouts nicht direkt erstellen.
  • Besseres und schnelleres Vorgehen des Benutzers durch Abgeben einiger Verarbeitungsschritte an asynchrone Aufrufe. Warum alles auf einmal? Wenn etwas Zeit hat, geben Sie ihm diese Zeit.

Future-Methoden

In Situationen, in denen Sie einen Callout bei einem Webservice vornehmen müssen oder einfache Verarbeitungsschritte an eine asynchrone Aufgabe abgeben möchten, kann es der richtige Weg sein, eine Future-Methode zu erstellen.

Eine Methode von einer synchronen in eine asynchronen Verarbeitung zu ändern, ist unglaublich einfach. Eigentlich müssen Sie nur die Anmerkung @future zu Ihrer Methode hinzufügen. Ansonsten vergewissern Sie sich einfach, dass die Methode statisch ist und nur einen void-Typ zurückgibt. Um beispielsweise eine Methode zur Durchführung eines Callouts bei einem Webservice zu erstellen, könnten Sie in etwa wie folgt vorgehen:

public class MyFutureClass {
    // Include callout=true when making callouts
    @future(callout=true)
    static void myFutureMethod(Set<Id> ids) {
        // Get the list of contacts in the future method since
        // you cannot pass objects as arguments to future methods
        List<Contact> contacts = [SELECT Id, LastName, FirstName, Email
            FROM Contact WHERE Id IN :ids];
        // Loop through the results and call a method
        // which contains the code to do the actual callout
        for (Contact con: contacts) {
            String response = anotherClass.calloutMethod(con.Id,
                con.FirstName,
                con.LastName,
                con.Email);
            // May want to add some code here to log
            // the response to a custom object
        }
    }
}

Dann könnten Sie einfach einen Aufruf vornehmen, wie Sie es bei jeder anderen statischen Methode auch tun würden. Ganz einfach, oder?

Future-Einschränkungen

Future-Methoden bieten Salesforce-Entwicklern zwar großartige Möglichkeiten, haben aber nicht nur Vorteile. Im Folgenden finden Sie einige Einschränkungen, die Sie berücksichtigen sollten, bevor Sie eine Future-Methode anwenden.

  • Sie können Ausführungen nicht nachverfolgen, da keine Apex-Auftrags-ID zurückgegeben wird.
  • Die Parameter müssen primitive Datentypen oder Sammlungen primitiver Datentypen sein. Future-Methoden können sObjects nicht als Argumente akzeptieren, da sich diese in der Zeit vor der Ausführung der @future-Methode ändern könnten.
  • Sie können Future-Methoden nicht verketten und eine Methode die nächste aufrufen lassen. Verwenden Sie Queueable-Apex, wenn die Ausführung in einer bestimmten Reihenfolge erfolgen soll.

Wenngleich asynchrone Aufrufe zuweilen durchgeführt werden, um Grenzen zu vermeiden, müssen Sie die Grenzen dennoch berücksichtigen. Schauen Sie sich den Link "Execution Governors and Limits" im Abschnitt "Ressourcen“ an.

Batch- oder geplantes Apex

Ein weiteres seit Langem verwendetes asynchrones Tool ist die Batchable-Schnittstelle. In erster Linie kommt sie zum Einsatz, wenn Sie eine große Anzahl an Datensätzen zu verarbeiten haben. Wenn Sie beispielsweise bis zu 150 Mio. Datensätze bereinigen oder archivieren wollen, ist die Batchable-Schnittstelle das Tool Ihrer Wahl. Sie können aber auch die Bulk-API 2.0 in Ihrem Apex-Code verwenden. Sie können Ihre Batches sogar so planen, dass sie zu einem bestimmten Zeitpunkt ausgeführt werden.

Um das Tool zu nutzen, implementiert Ihre Klasse die Database.Batchable-Schnittstelle. Darüber hinaus definieren Sie start()-, execute()- und finish()-Methoden. Anschließend können Sie mit der Database.executeBatch-Methode eine Batch-Klasse aufrufen. Mit dem folgenden Code wird z. B. eine Batchable-Klasse erstellt, die alle Accounts in einer Organisation verarbeitet, und nach Fertigstellung eine E-Mail gesendet.

global class MyBatchableClass implements
            Database.Batchable<sObject>,
            Database.Stateful {
    // Used to record the total number of Accounts processed
    global Integer numOfRecs = 0;
    // Used to gather the records that will be passed to the interface method
    // This method will only be called once and will return either a
    // Database.QueryLocator object or an Iterable that contains the records
    // or objects passed to the job.
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT Id, Name FROM Account');
    }
    // This is where the actual processing occurs as data is chunked into
    // batches and the default batch size is 200.
    global void execute(Database.BatchableContext bc, List<Account> scope) {
        for (Account acc : scope) {
            // Do some processing here
            // and then increment the counter variable
            numOfRecs = numOfRecs + 1;
        }
    }
    // Used to execute any post-processing that may need to happen. This
    // is called only once and after all the batches have finished.
    global void finish(Database.BatchableContext bc) {
        EmailManager.sendMail('someAddress@somewhere.com',
                              numOfRecs + ' Accounts were processed!',
                              'Meet me at the bar for drinks to celebrate');
    }
}

Anschließend könnten Sie die Batch-Klasse unter Verwendung von anonymem Code wie diesem aufrufen:

MyBatchableClass myBatchObject = new MyBatchableClass();
Database.executeBatch(myBatchObject);
Hinweis

In dieser Einheit sind wir nicht ausdrücklich auf das geplante Apex eingegangen, aber es ist ähnlich der Batchable-Schnittstelle. Es implementiert die planbare Schnittstelle und Sie können es einsetzen, um zu bestimmten Zeitpunkten ein Apex aufzurufen. Erfahren Sie mehr darüber, indem Sie sich das Modul Asynchrones Apex anschauen.

Batchable-Einschränkungen

Die Batchable-Schnittstelle ist toll, aber wie bei nahezu allem anderen, sind auch hier Einschränkungen zu berücksichtigen.

  • Die Fehlerbehebung kann mühsam sein.
  • Aufträge werden in Warteschlangen gestellt und sind von der Server-Verfügbarkeit abhängig, was zuweilen länger als erwartet dauern kann.
  • Haben wir schon über Grenzen gesprochen?

Und dann war da noch Queueable Apex

Über lange Zeit waren Future-Methoden und die Batchable-Schnittstelle die Hauptwege, die Entwicklern offen standen, um die asynchrone Verarbeitung durchzuführen. Aber erinnern Sie sich noch an all die Einschränkungen, von denen die Rede war? Durch sie sahen sich einige Entwickler mit Problemen konfrontiert, sodass es den Wunsch nach einer besseren Lösung gab.

Im Winter ’15 reagierte Salesforce mit Queueable Apex. Dabei handelt es sich um das Beste aus den Future-Methoden und der Batchable-Schnittstelle, die zu einem herausragenden asynchronen Tool zusammengefasst wurden. Entwickler, die gezwungen waren, die langsamere Batchable-Schnittstelle zu verwenden, um die Einschränkungen der Future-Methoden zu umgehen, konnten sich nun eines Tools bedienen, das wesentlich sinnvoller war. Queueable Apex bietet gegenüber den Future-Methoden die folgenden Vorteile.

  • Nicht primitive Typen – Klassen können Parametervariablen mit nicht primitiven Datentypen akzeptieren, wie etwa sObjects oder benutzerdefinierte Apex-Typen.
  • Überwachung – Wenn Sie Ihren Auftrag senden, wird eine Auftrags-ID zurückgegeben, anhand derer Sie den Auftrag identifizieren und seinen Fortschritt überwachen können.
  • Verketten von Aufträgen – Sie können zwei Aufträge miteinander verketten, indem Sie einen zweiten Auftrag aus einem laufenden Auftrag heraus starten. Das Verketten von Aufträgen ist bei der sequenziellen Verarbeitung hilfreich.

Wie funktioniert das? Das ist eine sehr wichtige Frage!

Da Queueable Apex das Beste der Future-Methoden beinhaltet, ist es viel leichter zu implementieren als Batch-Apex. Es hat einfach nicht diese ärgerlichen Einschränkungen, über die wir ja schon gesprochen haben. Nehmen wir zu Demonstrationszwecken also den Beispielcode, der eine Future-Methode verwendet, um einen Web-Callout durchzuführen und ihn mithilfe des Queueable Apex zu implementieren.

public class MyQueueableClass implements Queueable {
    private List<Contact> contacts;
    // Constructor for the class, where we pass
    // in the list of contacts that we want to process
    public MyQueueableClass(List<Contact> myContacts) {
        contacts = myContacts;
    }
    public void execute(QueueableContext context) {
        // Loop through the contacts passed in through
        // the constructor and call a method
        // which contains the code to do the actual callout
        for (Contact con: contacts) {
            String response = anotherClass.calloutMethod(con.Id,
                    con.FirstName,
                    con.LastName,
                    con.Email);
            // May still want to add some code here to log
            // the response to a custom object
        }
    }
}

Zum Aufrufen des Queueable Apex benötigen Sie z. B. Folgendes:

List<Contact> contacts = [SELECT Id, LastName, FirstName, Email
    FROM Contact WHERE Is_Active__c = true];
Id jobId = System.enqueueJob(new MyQueueableClass(contacts));

Weitere Infos

Neben den Queueable-Schnittstellen führte Salesforce in der Version Spring ’15 auch die Flexible Apex-Warteschlange ein, durch die die Einschränkung von fünf gleichzeitig verarbeiteten Batches vermieden werden. Außerdem können Entwickler mit ihrer Hilfe die Reihenfolge der Aufträge in der Warteschlange überwachen und verwalten. Weitere Informationen finden Sie unter den Links im Abschnitt "Ressourcen".

In diesem Modul wurden den .NET-Entwicklern die in der Lightning-Plattform verfügbaren asynchronen Optionen näher gebracht. Nähere Informationen zu diesem Thema einschließlich Tests, des Überwachens von Aufträgen und bewährter Vorgehensweisen finden Sie im Modul Asynchrones Apex.

Ressourcen

Teilen Sie Ihr Trailhead-Feedback über die Salesforce-Hilfe.

Wir würden uns sehr freuen, von Ihren Erfahrungen mit Trailhead zu hören: Sie können jetzt jederzeit über die Salesforce-Hilfe auf das neue Feedback-Formular zugreifen.

Weitere Infos Weiter zu "Feedback teilen"