3

We have a very complex scenario where we have multiple external systems that we interact with and we need to make sure the data is valid across multiple external systems before it gets processed within Salesforce. I know there is Queueable Asynchronous Transaction in Apex, but I'm looking for something similar to Promises in JavaScript.

So in JavaScript, it would be something like this....

    var p1 = helper.calloutExternalSystem(component,'verifyExternalSystem1');
    var p2 = helper.calloutExternalSystem(component,'verifyExternalSystem2');
    var p3 = helper.calloutExternalSystem(component,'verifyExternalSystem3');

    var p = Promise.all([p1,p2,p3]);

    p.then(function(result){
        console.log('Promise.all');
        console.log(result);
    });

In Salesforce Apex, how can we achieve something similar in Apex? If it's not doable in Apex, how do most work around the situation? Any guidance is greatly appreciated.

6
  • It can't be done as you are asking for.
    – Adrian Larson
    Apr 8, 2022 at 16:34
  • I'm sure this is a common use case, what does the industry go about achieving such external validations?
    – jojopogi
    Apr 8, 2022 at 16:35
  • External validations are actually not all that common in my experience.
    – Adrian Larson
    Apr 8, 2022 at 16:36
  • 1
    From Event-Driven Architecture decision guide: The best way to coordinate logic across multiple automations is to use subflows or Flow Orchestrator. Unlike platform events, subflows are not subject to event allocation limits
    – identigral
    Apr 8, 2022 at 16:48
  • Just to clarify. Is your intention to make sure that every promise p1, p2, p3 must be successfull and only then the promise p should be executed? In other words p is the transaction that will be rolled back / not executed if one of p1, p2, p3 were unsuccessfull. Is this the case? Is p meant as a transaction?
    – surfmuggle
    Oct 12, 2022 at 9:43

3 Answers 3

3

There isn't a native equivalent of a Promise in Apex, but since you can make asynchronous calls, you can build a Promise-like functionality on top of that.

One example of such a library is this one from Kevin Poorman: https://github.com/codefriar/promise

1
  • Thank you! This solves my programming problem :)
    – jojopogi
    Apr 14, 2022 at 18:09
2

Probably the best you can do is persist the data from your callouts into a new object. Or if you are already working with one, persist the callout state there. Then you can add a section in your trigger handler logic which checks for all of the callouts being complete, and executes subsequent processing.

List<MyObject__c> haveAllCalloutsCompleted = new List<MyObject__c>();
for (MyObject__c record : trigger.new)
    if (record.Callout_1_Complete__c && record.Callout_2_Complete__c && record.Callout_3_Complete__c)
        haveAllCalloutsCompleted.add(record);
executeSubsequentProcessing(haveAllCalloutsCompleted);

Note the above is a simplified version, you would need to incorporate filtering to check if any of the fields changed to detect when you are in the correct transaction that the final box gets checked (and not further downstream).

1

For up to three callouts specifically, you can use continuations. This works for Visualforce, Aura, and LWC. Obviously, this won't work for triggers and such. If you want to do this in asynchronous code, just call each API one at a time, it shouldn't matter unless you need more than 120 seconds worth of callout time.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .