kurofune
kurofune

Reputation: 1095

How do you time consecutive events in the browser, using Javascript in an HTML script tag?

I have just started learning JavaScript, coming from a Java/Clojure background and I am trying to do a simple thread-sleep command that will allow me to have lines of text appear on the screen, at one second intervals. I thought about using the setInterval function instead, but because I am dealing with multiple functions, I thought setTimeout would be better. The problem I am encountering is that all of the text is printing in the browser instantaneously, as though the setTimeout functions weren't even there. Below is an example using the "Happy Birthday" song, which I think succinctly illustrates the problem. How can I make the program below run, line by line, at one second intervals?

<!doctype html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>Happy Birthday</title>
        </head>
        <body>
            <script>
                var name = "Joe",
                    i = 0;

                while (i < 2) {
                    setTimeout(document.write("Happy Birthday to you!<br>"), 1000);
                    i ++;
                }
                setTimeout(document.write("Happy Birthday dear " + name + ",<br>"), 1000);
                setTimeout(document.write("Happy Birthday to you!<br>"), 1000);
            </script>
        </body>
    </html>

Upvotes: 0

Views: 417

Answers (2)

raina77ow
raina77ow

Reputation: 106385

To delay evaluation of some code, this code should be put into a function; that function reference should be passed into setTimeout. For example:

setTimeout(function() {
    document.write('Hello world!');
}, 1000);

As it stands, you evaluate document.write expression instead immediately - that's why you see all the writings occurring simultaneously.

As a sidenote, please please please don't use document.write unless you're really know what're you're doing. It's quite easy to 'log' something just by adjusting innerHTML of log element. For example:

<div id="log"></div>
<script>
  var log = document.getElementById('log');
  setTimeout(function() {
    log.innerHTML += 'Hello world!<br />';
  }, 1000);
</script>

Also, don't forget that each timeout is processed independently. To set up a chain of events, you'd manually increase the delay - otherwise all the functions will be called almost immediately after each other.

Overall, here's how it can be done:

<div id="log"></div>
<script>
var name = "Joe",
    i = 0,
    delayedMessage = function(msg) {
      setTimeout(function() {
        document.getElementById('log').innerHTML += msg;
      }, ++i * 1000);
    };

    delayedMessage("Happy Birthday to you!<br>");
    delayedMessage("Happy Birthday to you!<br>");
    delayedMessage("Happy Birthday dear " + name + ",<br>");
    delayedMessage("Happy Birthday to you!<br>");
</script>

Demo.

Upvotes: 2

Augusto Altman Quaranta
Augusto Altman Quaranta

Reputation: 1576

In your code you were executing the document.write and then setting the timeout handler with its return value which is clearly wrong.

Remember you must always pass a function (a handler) to every event you want to react to.

So, the correct code is:

setTimeout(function(){
    document.write("Happy Birthday to you!<br>");
}, 1000);

Upvotes: 0

Related Questions