0

I have a button to perform a calculation and an indicator:

<button class="btn" type="button" onclick="$('#busy').show(); calculate();">Ok</button>
<div id="busy" style="display: none;">Calculating...</div>

What the browser does in this case is calculate(), and then show the div Same problem when the calculate() function first tries to show the div and then calculates.

How do I make the events happen in the intended order?

EDIT: Maybe the css does change before the calculation, but it is not rendered until after the calculation. Also tried with click event handling but same thing.

http://jsfiddle.net/Z7rAJ/

5
  • You should describe your problem a little better. Commented Jun 21, 2013 at 10:41
  • browser doesn't have enough time to redraw the UI maybe. The question could be what make you think calculate() is called before? Commented Jun 21, 2013 at 10:45
  • Calculate takes about 10 seconds. It takes 10 seconds for the div to show. Commented Jun 21, 2013 at 10:47
  • So, please consider to provide a jsfiddle to reproduce your issue. Or at least, show us code of calculate() function. And is it on all browser or specific to one? Commented Jun 21, 2013 at 10:53
  • jsfiddle.net/Z7rAJ Commented Jun 21, 2013 at 11:05

2 Answers 2

2

jQuery's .show() does nothing else than performing a change in the display css property (alongside some magic on previous states).

However, everything happens in syncronized code. Its virtually impossible that your calculate() method is called first here.


Its much more likely that your calculate() method is doing some heavy synronized, blocking operations and that the browser batches the two code segements together. It happens to be that in browsers, Javascript code, CSS Rendering and general "UI repaints and reflows", are processed in the same queue and therefore in the same thread. I'm talking about the such called "UI Queue" here.

In short words, you need to make your calculate() function "faster", decouple it into smaller chunks. The worst option would be to entirely defer the calling of calculate() by invoking a setTimeout. That latter would solve your immediate problem, but it would still block the browser and the UI queue afterwards.

Example: http://jsfiddle.net/5E2bn/1/

As I already stated, you don't really want to do that, its just an example to make the point clear. In any real-world scenario you should go back to the drawing board and think about what calculate() does here and how you can split it up into smaller chunks.

One very convenient way to decouple long-running processes in Javascript is the usage of Run-away script timers, which basically chunk a sync loop into multiple asyncronous loops to give the UI queue and the browser time to breath in between code executions.

Sign up to request clarification or add additional context in comments.

2 Comments

@roasted that might well be. But it wouldn't change anything on the order of code execution
Thanks. The timeout works. calculate() can't really be more efficient or be split, it generates public/private key pairs.
0

Do something like coz setTimeout might not be a good option

$('.btn').click(function() {
    if (calculate()) {
        $('#busy').show();
    }
});

Make sure you return true or false : #busy will be shown only once the value from calculate() function is returned

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.