0

I have a static method named ABC in apex which is called multiple times from aura due to iteration.

So in ABC I have few methods which need to be called only once in the first iteration.

How can I prevent this inner methods from executing multiple times?

I tried with various approach but not working.

4
  • I recommend you edit your question to make it clearer what you are trying to do, including adding some code or screenshots to illustrate what you have done so far.
    – Phil W
    Mar 4, 2021 at 14:39
  • 3
    From my reading in this, you need to make sure you pass the iteration count from Aura to the Apex and have the Apex only perform the other methods when that count is 0.
    – Phil W
    Mar 4, 2021 at 14:41
  • YeaYou got it correct. I started with that. But feeling weird. Is it a bad approach.
    – NBR
    Mar 4, 2021 at 15:13
  • Whether this is a good or bad approach depends on the processing you are doing. @StephenSS's approach is good for modest numbers of items and little specific processing for each, especially when you bulkify all the processing. If that doesn't fit for you, use the index approach. Remember, however, that in-memory state set up in one call from Aura is not visible to other calls from Aura.
    – Phil W
    Mar 4, 2021 at 16:12

3 Answers 3

1

Rather than iterating in aura and making a single request for each iteration, it may be possible to refactor in order to make a single request in aura passing the iterable thing to a refactored ABC that takes the matching type of iterable, then in ABC you can make decisions based on whether or not this is the first iteration.

Clarification: Instead of this pattern:

items.forEach( ( item ) => helper.updateOnServer( item ) );

...

ABC( Item__c item ) {
   // call some methods
}

You should try to refactor so that you can do something like this:

helper.updateOnServer( items );

...

ABC( List<Item__c> items ) {
    Boolean firstPass = true;
    for ( Item__c item : items ) {
        if ( firstPass ) {
            // do some things once
            firstPass = false;
        }
        // do some other things all the time
    }
}
6
  • Can u make it more clear? I am sending the request to apex for every iteration
    – NBR
    Mar 4, 2021 at 15:04
  • OK. I've added some fake code to try and help illustrate what I mean.
    – Stephen SS
    Mar 4, 2021 at 15:13
  • Will this approach make any kind of performance improvement do u think
    – NBR
    Mar 4, 2021 at 15:15
  • It really depends on the actual code that is running on both ends but, in general, the fewer round trips to the server and back, the better. There may also be considerations within a refactored ABC (things like query limits and so on) that you run into due to looping on the server. It's very hard to say if this will suit you, but if it does then it's worth a try to solve the issue.
    – Stephen SS
    Mar 4, 2021 at 15:20
  • 1
    Looks like a good approach to me. Note, however, this only works if you are not spending too much CPU time (or other per-transaction governor limits) in processing each entry in the list and the list isn't too big. The benefit of doing separate requests from Aura, where the client "orchestrates" the processing is that you have full limits for each request from the Aura component for each item.
    – Phil W
    Mar 4, 2021 at 16:09
1

You might consider creating an @AuraEnabled method that calls the methods you only want to run once, and execute that first from LWC. Then you can exclude the one-off apex methods entirely from the iterated calls. You add an additional server call, yes, but with the benefit of greater code simplicity, maintainability, and elegance. Any performance degradation should be unnoticeable.

Example (your method ABC is runOnEachIteration here for clarity):

CHANGE

// LWC:
for (const item of items) {
    await runOnEachIteration();
}

// APEX:
@AuraEnabled
public static void runOnEachIteration() {
    if (/* try to figure out if it hasn't been run yet */) {
        doThisOnce();
        doThatOnce();
    }
    
    doThisForEach();
}

INTO

// LWC:
if (items.length > 0) {
    await runOnce();
    for (const item of items) {
        await runOnEachIteration();
    }
}

// APEX:
@AuraEnabled
public static void runOnce() {
    doThisOnce();
    doThatOnce();
}

@AuraEnabled
public static void runOnEachIteration() {
    doThisForEach();
}
0

This is called as Recursion.

In order to handle the recursive calls, we can use static boolean variable(s) and check its values, that is, you can use static Boolean variable with default value true and in the trigger/desired logic, before executing your code you can keep a check that the variable is true or not. Once you check make the variable as false, that will avoid the logic from being called again.

SF basic article to handle Recursion.

Another SF article that stresses best practices to avoid recursion.

4
  • But on the next transaction it is again initialized to default value right?
    – NBR
    Mar 4, 2021 at 14:11
  • Be aware that both references point to articles that actually describe the use of an invalid means to block recursion in triggers. See this previous Q&A or any one of a bunch of others for explanation as to why this is an anti-pattern.
    – Phil W
    Mar 4, 2021 at 14:12
  • But I am not at all referencing to trigger
    – NBR
    Mar 4, 2021 at 14:14
  • Is it possible to get the old value in apex?
    – NBR
    Mar 4, 2021 at 14:16

You must log in to answer this question.

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