Skip to main content
Nehmen Sie teil an unserer 5-minütigen Community-Umfrage, geöffnet ab sofort und noch bis zum 30. November. Klicken Sie hier, um mitzumachen.

Verwenden von Future-Methoden

Lernziele

Nachdem Sie diese Lektion abgeschlossen haben, haben Sie Folgendes gelernt:

  • Zeitpunkt für die Verwendung von Future-Methoden
  • Einschränkungen bei der Verwendung von Future-Methoden
  • Verwenden von Future-Methoden für Callouts
  • Future-Methoden – bewährte Vorgehensweisen
Hinweis

Hinweis

Lernen Sie auf Deutsch? Beginnen Sie die Aufgabe in einem Trailhead Playground in der Sprache Deutsch und verwenden Sie für die Navigation die in Klammern angegebenen Übersetzungen. Kopieren und fügen Sie nur die Angaben in Englisch ein, da zur Überprüfung der Aufgabe Daten in Englisch benötigt werden. Wenn Sie die Aufgabe in Ihrer deutschen Organisation nicht bestehen, empfehlen wir Ihnen folgende Vorgehensweise: (1) Stellen Sie das Gebietsschema auf USA um, (2) legen Sie Englisch als Sprache fest (Anweisungen dazu finden Sie hier) und (3) klicken Sie erneut auf die Schaltfläche "Check Challenge" (Aufgabe überprüfen).

Weitere Details dazu, wie Sie die übersetzte Trailhead-Umgebung optimal nutzen können, finden Sie unter dem Badge "Trailhead in Ihrer Sprache".

Mit Trail Together einem Dozenten folgen

Möchten Sie bei diesem Schritt einem Dozenten folgen? Sehen Sie sich dieses Video an, das zur Serie "Trail Together" auf Trailhead Live gehört.

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

Future-Apex

Apex-Methoden mit der @future-Kennzeichnung (die im weiteren Verlauf dieses Moduls als “Future-Methoden” bezeichnet werden) werden asynchron in einem separaten Thread ausgeführt, zu einem späteren Zeitpunkt, wenn Systemressourcen verfügbar werden.

Hinweis

Im Allgemeinen wird die Verwendung von Queuable Apex anstelle von Apex Future-Methoden empfohlen. Queueables weisen die gleichen Anwendungsfälle wie Future-Methoden auf, bieten aber zusätzliche Vorzüge, darunter Auftrags-IDs, Unterstützung für nicht primitive Typen und Verkettung von Aufträgen.

Bei Verwendung der synchronen Verarbeitung erfolgen alle Methodenaufrufe aus dem gleichen Thread, der auch den Apex-Code ausführt, und es ist keine weitere Verarbeitung möglich, bis der Prozess abgeschlossen ist. Sie können Future-Methoden für jeden Vorgang verwenden, den Sie asynchron in seinem eigenen Thread ausführen möchten. Asynchrone Verarbeitung bietet den Vorteil, den Benutzer nicht am Ausführen anderer Vorgänge zu hindern. Ferner stellt sie dem Prozess höhere Obergrenzen für die Ausführung zur Verfügung. Es profitieren also alle Seiten von der asynchronen Verarbeitung.

Future-Methoden werden meist für folgende Zwecke verwendet:

  • Callouts an externe Webservices. Wenn Sie Callouts von einem Auslöser aus oder nach der Durchführung eines DML-Vorgangs durchführen, müssen Sie eine Future-Methode oder die Queueable-Schnittstelle verwenden. Durch einen Callout in einem Auslöser würde andernfalls die Datenbankverbindung für die gesamte Lebensdauer des Callouts aufrecht erhalten und das ist in einer mandantenfähigen Umgebung sehr kostspielig.
  • Vorgänge, die Sie in ihrem eigenen Thread ausführen möchten, wenn der Zeitpunkt günstig ist, wie z. B. eine ressourcenintensive Berechnung oder Datensatzverarbeitung.
  • Isolieren von DML-Vorgängen für verschiedene sObject-Typen, um den Mixed DML-Fehler zu vermeiden. Dieser Anwendungsfall tritt jedoch eher selten auf. Weitere Einzelheiten finden Sie unter sObjects That Cannot Be Used Together in DML Operations.

Syntax von Future-Methoden

Future-Methoden müssen statische Methoden sein und dürfen nur einen void-Typ zurückgeben. Die angegebenen Parameter müssen primitive Datentypen oder Sammlungen primitiver Datentypen sein. Vor allem dürfen bei Future-Methoden keine standardmäßigen oder benutzerdefinierten Objekte als Argumente angegeben werden. Im allgemeinen wird der Methode eine List (Liste) mit Datensatz-IDs übergeben, die asynchron verarbeitet werden sollen.

public class SomeClass {
  @future
  public static void someFutureMethod(List<Id> recordIds) {
    List<Account> accounts = [Select Id, Name from Account Where Id IN :recordIds];
    // process account records to do awesome stuff
  }
}
Hinweis

Der Grund, aus dem Objekte nicht als Argumente an Future-Methoden übergeben werden dürfen, besteht darin, dass sich das Objekt zwischen dem Zeitpunkt des Methodenaufrufs und dem Zeitpunkt der eigentlichen Ausführung ändern kann. Sie erinnern sich? Future-Methoden werden ausgeführt, wenn Systemressourcen verfügbar werden. Die Future-Methode könnte sonst bei ihrer tatsächlichen Ausführung einen alten Objektwert enthalten, was alle möglichen negativen Auswirkungen haben könnte.

Hier muss unbedingt darauf hingewiesen werden, dass es nicht garantiert ist, dass Future-Methoden in derselben Reihenfolge ausgeführt werden, in der sie aufgerufen wurden. Wir weisen nochmals darauf hin, weil Sie dies wirklich unbedingt beachten müssen: Future-Methoden werden nicht mit Sicherheit in derselben Reihenfolge ausgeführt, in der sie aufgerufen wurden. Bei der Verwendung von Future-Methoden besteht zudem die Möglichkeit, dass zwei Future-Methoden gleichzeitig ausgeführt werden. Dies kann zu einer Datensatzsperre und einem Laufzeitfehler führen, wenn die beiden Methoden denselben Datensatz aktualisieren.

Callout-Beispielcode

Wenn Sie einen Webservice-Callout zu einem externen Service oder einer API durchführen möchten, erstellen Sie eine Apex-Klasse mit einer Future-Methode, die mit (callout=true) gekennzeichnet wird. Die nachfolgende Klasse enthält zwei Methoden: eine für die synchrone und eine für die asynchrone Callout-Durchführung, sofern synchrone Callouts nicht zulässig sind. Der synchrone Aufruf fügt außerdem einen Datensatz in ein benutzerdefiniertes Protokollobjekt ein, um den Status des Callouts nachzuverfolgen.

Hinweis

Die Klasse SmsMessage und das sObject SMS_Log__c im Beispiel sind hypothetisch und werden nur angezeigt, um das Callout-Muster zu demonstrieren.

public class SMSUtils {
    // Call async from triggers, etc, where callouts are not permitted.
    @future(callout=true)
    public static void sendSMSAsync(String fromNbr, String toNbr, String m) {
        String results = sendSMS(fromNbr, toNbr, m);
        System.debug(results);
    }
    // Call from controllers, etc, for immediate processing
    public static String sendSMS(String fromNbr, String toNbr, String m) {
        // Calling 'send' will result in a callout
        String results = SmsMessage.send(fromNbr, toNbr, m);
        insert new SMS_Log__c(to__c=toNbr, from__c=fromNbr, msg__c=results);
        return results;
    }
}

Testklassen

Das Testen von Future-Methoden unterscheidet sich etwas vom normalen Apex-Testen. Zum Testen von Future-Methoden fügen Sie Ihren Testcode zwischen die Testmethoden startTest() und stopTest() ein. Das System sammelt alle asynchronen Aufrufe, die nach 'startTest()' durchgeführt werden. Wenn stopTest() ausgeführt wird, werden alle diese gesammelten, asynchronen Prozesse synchron ausgeführt. Sie können dann sicherstellen, dass der asynchrone Aufruf richtig funktioniert hat.

Hinweis

Da der Testcode keine echten Callouts an externe Systeme senden kann, müssen Sie den Callout für die Testabdeckung simulieren. Ausführliche Details zum Simulieren von Callouts beim Testen finden Sie im Modul Apex-Integrationsservices.

Hier sehen Sie unsere simulierte Callout-Klasse, die beim Testen verwendet wird. Das Apex-Test-Framework nutzt diese "simulierte" Antwort, anstelle den tatsächlichen Callout an den REST API-Endpunkt durchzuführen.

@isTest
public class SMSCalloutMock implements HttpCalloutMock {
    public HttpResponse respond(HttpRequest req) {
        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"status":"success"}');
        res.setStatusCode(200);
        return res;
    }
}

Die Testklasse enthält eine einzige Testmethode (testSendSms() in diesem Beispiel), die sowohl die asynchrone als auch die synchrone Methode testet, da die asynchrone die synchrone Methode aufruft.

@IsTest
private class Test_SMSUtils {
  @IsTest
  private static void testSendSms() {
    Test.setMock(HttpCalloutMock.class, new SMSCalloutMock());
    Test.startTest();
      SMSUtils.sendSMSAsync('111', '222', 'Greetings!');
    Test.stopTest();
    // runs callout and check results
    List<SMS_Log__c> logs = [select msg__c from SMS_Log__c];
    System.assertEquals(1, logs.size());
    System.assertEquals('success', logs[0].msg__c);
  }
}

Bewährte Vorgehensweisen

Da bei jedem Aufruf einer Future-Methode eine Anforderung zur asynchronen Warteschlange hinzugefügt wird, sollten Sie Designmuster vermeiden, bei denen in einem kurzen Zeitraum viele Future-Anforderungen hinzugefügt werden. Wenn Ihr Design das Potenzial hat, 2000 oder mehr Anforderungen gleichzeitig hinzuzufügen, könnten Anforderungen aufgrund der Datenflusssteuerung verzögert werden.

Hier sind einige bewährte Vorgehensweisen, die Sie im Hinterkopf behalten sollten:

  • Stellen Sie sicher, dass Future-Methoden so schnell wie möglich ausgeführt werden.
  • Versuchen Sie bei der Verwendung von Webservice-Callouts, alle Callouts innerhalb derselben Future-Methode zu bündeln, anstatt für jeden Callout eine separate Future-Methode zu verwenden.
  • Führen Sie gründliche Tests in der gewünschten Skalierung durch. Testen Sie, ob ein Auslöser, der die @future-Aufrufe in die Warteschlange einreiht, eine Auslösersammlung von 200 Datensätzen verarbeiten kann. Damit können Sie die Wahrscheinlichkeit von Verzögerungen für das Design mit dem aktuellen und künftigen Volumen feststellen.
  • Ziehen Sie die Verwendung von Batch-Apex anstelle von Future-Methoden für die asynchrone Verarbeitung großer Datensatzmengen in Erwägung. Dies ist effizienter als die Erstellung einer Future-Anforderung für jeden Datensatz.

Wichtige Punkte

Future-Methoden sind ein mächtiges Tool, doch große "Macht" bedeutet auch große Verantwortung. Hier sind einige Punkte, die Sie bei der Arbeit mit Future-Methoden beachten sollten:

  • Methoden mit der Anmerkung @future müssen statische Methoden sein und dürfen nur einen void-Typ zurückgeben.
  • Die angegebenen Parameter müssen primitive Datentypen oder Sammlungen primitiver Datentypen sein. Bei Future-Methoden dürfen keine Objekte als Argumente angegeben werden.
  • Future-Methoden werden nicht zwingend in der Reihenfolge ausgeführt, in der sie aufgerufen werden. Es besteht zudem die Möglichkeit, dass zwei Future-Methoden gleichzeitig ausgeführt werden. Dies kann zu einer Datensatzsperre führen, wenn die beiden Methoden denselben Datensatz aktualisieren.
  • Future-Methoden können weder in Visualforce-Steuerfeldern in getMethodName() oder setMethodName() noch im Konstruktor verwendet werden.
  • Eine Future-Methode kann nicht innerhalb einer Future-Methode aufgerufen werden. Sie können auch nicht während der Ausführung einer Future-Methode einen Auslöser aufrufen, der eine Future-Methode aufruft. Zum Vermeiden rekursiver Future-Methodenaufrufe sollten Sie System.isFuture() verwenden, das true zurückgibt, wenn der aktuell ausgeführte Code von Code aufgerufen wird, der in einer Future-Methode enthalten ist.
  • Die Methoden getContent() und getContentAsPDF() dürfen in Methoden mit der Anmerkung @future nicht verwendet werden.
  • Pro Apex-Aufruf dürfen maximal 50 Future-Methoden aufgerufen werden. Zusätzlich gibt es noch ein Limit für die Anzahl der Aufrufe innerhalb von 24 Stunden. Mehr dazu erfahren Sie unter Execution Governors and Limits.

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"