2

I have an <apex:actionFunction> which can take a long while to complete. While the action function is executing, I would like to be able to execute some on page JavaScript to make the users waiting experience more interesting (Changing onscreen messages etc)

  1. Call action function.
  2. Run on page JavaScript.
  3. When action function completes, stop on page JavaScript and run oncomplete code.

However, it seems that JavaScript is single threaded. Is there any way round this?

Thanks

3

A single event function is single-threaded in nature, and JavaScript itself generally behaves as if it were single-threaded (but WebWorkers provide multiple threads, and event handlers can execute in apparently multiple threads, as per a discussion on SE).

The best way to ensure a concurrent effect is to use setTimeout or setInterval on the animation function, thus allowing the browser to execute the animation periodically while processing occurs.

A demonstration of this animation procedure follows:

<script>
    var timerId = null;
    function doAnimationFrame() {
        // animation code here
    }
    function startAnimation() {
        timerId = setInterval(doAnimationFrame, 50); // 50ms is ~20 frames/second
    }
    function stopAnimation() {
        clearInterval(timerId);
    }
</script>
<!-- ... -->
<apex:actionFunction name="controllerFunction" action="{!controllerFunction}" reRender="form" oncomplete="stopAnimation()"/>
<apex:commandButton onclick="startAnimation(); controllerFunction(); return false;" value="Do Something!" />
2

Try to execute a second javascript function just right after the action function. Then execute the second function again on oncomplete but with another parameter to stop the first execution and start another code. Something like this:

<script>
function function2(param){
    if(param == "start"){
        // start your stuff
    }
    else{
        // execute another code
    }
}
</script>

<apex:actionFunction name="function1" 
                     reRender="none" 
                     action="{!someAction}" 
                     oncomplete="function2('stop')"/>

<apex:commandButton onclick="function1(); function2('start'); return false;" />
3
  • 1
    Or, one could do: window.timerId = setInterval(function2,50); function1(); return false;, and then the oncomplete could be clearInterval(window.timerId). This makes it clear that the code is meant to be run asynchronously. If function1 later becomes blocking (implementation change), the animation would still run. – sfdcfox Aug 28 '13 at 19:56
  • Thank you both for your answer and comment. I ended up using @sfdcfox's method which worked really great for my purpose. Is it possible you could make your comment into an answer so I can accept it? – Joe Aug 29 '13 at 8:24
  • As you requested, Joe. I also included a link about Web Workers and JavaScript concurrency from SE. They might offer you additional options to pursue. – sfdcfox Aug 29 '13 at 13:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.