最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript does not print text immediately - Stack Overflow

programmeradmin4浏览0评论

I wrote this code which is supposed to say "hi" when I click the "hello" button:

<!DOCTYPE html>

<html>

<head>
<script>
var someLargeNumber = 5000000000;
function hello() {
    document.getElementById('hi').innerHTML = "hi";
    for(var i = 0; i < someLargeNumber; i++) {}
}
</script>
</head>

<body>
<p id="hi"></p>
<input type="button" value="hello" onclick="hello();">
</body>

</html>

It does say hi, but only after the for loop is finished. Why does this happen and how do I fix this?

Thanks

I wrote this code which is supposed to say "hi" when I click the "hello" button:

<!DOCTYPE html>

<html>

<head>
<script>
var someLargeNumber = 5000000000;
function hello() {
    document.getElementById('hi').innerHTML = "hi";
    for(var i = 0; i < someLargeNumber; i++) {}
}
</script>
</head>

<body>
<p id="hi"></p>
<input type="button" value="hello" onclick="hello();">
</body>

</html>

It does say hi, but only after the for loop is finished. Why does this happen and how do I fix this?

Thanks

Share Improve this question asked Nov 26, 2015 at 13:58 user5350242user5350242 1
  • 3 Maybe you could take out the loop. Why is it there? The browser won't (necessarily) re-render the page until the "click" handler is finished. – Pointy Commented Nov 26, 2015 at 14:00
Add a ment  | 

2 Answers 2

Reset to default 23

Why does this happen...

Because browsers run JavaScript on the main UI thread they use for updating the page, for a variety of reasons. So although you've shown the "hi" text, it doesn't get rendered until the JavaScript code running in response to the event pletes.

...and how do I fix this?

Yield back to the browser after adding the text, before doing whatever it is that you're simulating with that loop. setTimeout with a delay of 0 is suitable for many cases:

var someLargeNumber = 5000000000;
function hello() {
    document.getElementById('hi').innerHTML = "hi";
    setTimeout(function() {
        for(var i = 0; i < someLargeNumber; i++) {}
    }, 0);
}

The JavaScript engine works basically in a loop with a task queue (the spec calls them "jobs"). It picks up a job from the queue, runs it to pletion, and then looks for the next job. Browsers (usually) update the UI when the engine is between jobs. When an event occurs, a job is queued to call the event handler. The above just moves the loop into a new job it queues via setTimeout, so the browser has a chance after the event job and before the setTimeout job to update the UI.

As already answered browser has single UI thread.

Another option is to use Web Worker (provided you are not doing any DOM manipulations in the worker thread), which allows to run operations in an another thread.

Add another js file (say worker.js)

var someLargeNumber = 5000000000;
onmessage = function(e) {
  console.log('Message received from main script');
  for(var i = 0; i < someLargeNumber; i++) {}
  console.log('Posting message back to main script');
  postMessage('done');
}

Back in you main file

<head>
<script>
var myWorker = new Worker("worker.js");
function hello() {
    document.getElementById('hi').innerHTML = "hi";
    myWorker.postMessage('test');
    console.log('Message posted to worker');
}
myWorker.onmessage = function(e) {
  result.textContent = e.data;
  console.log('Worker thread is plete');
}
</script>
发布评论

评论列表(0)

  1. 暂无评论