Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Im sure this has been asked 1000 times before, basically all I want to do is change the content of an element of the page to display a loading message while my other javascript code (quite resource intensive) completes. The problem is the message isnt displayed untill after the "other JS processing" has completed, thus defeating its purpose entirely. a simplified example...

<html>
<head>
    <title> crappity crapness </title>
    <script type="text/javascript">
        function showMessage(){
            document.getElementById("content").innerHTML = "please wait while we waste some time";
        }

        function wasteTime(){
            //alert("oh joy");
            pausecomp(3000);
            //alert("marvelous!");
        }

        function pausecomp(millis) 
        {
            var date = new Date();
            var curDate = null;

            do { curDate = new Date(); } 
            while(curDate-date < millis);
        } 

    </script>
</head>
<body>
    <div id="content">Blah</div>
    <br/>
    <a href="http://www.google.com" onclick="showMessage(); wasteTime();"> link </a>
</body>

if I uncomment the "oh Joy" alert, the text in the div gets updated Immediatly. how do I make it work without the alert?

I know I must be missing something simple. Thanks

share|improve this question
add comment

3 Answers

up vote 3 down vote accepted

It sounds like you're coming up against the fact that Javascript is single-threaded, but browsers are not.

Basically, you can't have multiple pieces of Javascript running at once. However, the browser still has to do things outside of executing Javascript and proceeds to do so when it can. The problem is that whether modifying the DOM is synchronous (i.e. JS execution stops until it's done) or asynchronous (JS execution continues) isn't defined. Most browsers do the latter. But JS execution still has a quite high priority and a lot of DOM updates get deferred until the JS execution has to stop and wait. An alert box is an excellent example because it is waiting for user input.

The way to do what you want to do is to advantage of setTimeout() which lets the current piece of JS finish, the browser can then finish updating the DOM, and then it can execute JS waiting to run on a timeout.

share|improve this answer
 
good explanation, Thanks for that. I was hoping to do it without using setTimeout (as it was validation in the onSubmit of a form), but it appears there is no other way. anyway, I guess a delay of a millisecond isnt too bad! –  hendinas Mar 31 '11 at 7:18
add comment

What would be nice if you could do would be to call the showMessage function asynchronously. In other languages, you could do this with threads, and in HTML5 you can do this with workers, which are designed exactly for this sort of thing, but for right now you can most simply just use setTimeout, which makes the code in the first argument execute after a certain amount of time, allowing the current code to execute before it does.

Change

   onclick="showMessage(); wasteTime();"

to

   onclick="showMessage; setTimeout(wasteTime,5);"> 
share|improve this answer
 
yep, thats it. I was trying to do it without a setTimeout, but I guess its not so bad if its only delaying it by a milisecond! Thanks. –  hendinas Mar 31 '11 at 6:41
add comment

Your pausecomp(3000) is essentially blocking the browser from redrawing because of the while loop. I would do something like this instead :

function wasteTime(){
    setTimeout(runNext, 3000);
}

function runNext(){
     alert("marvelous!");
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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