0

I would like to change the content of a paragraph while the button handler is running rather than waiting for the button handler to finish. Here is my code:

Output: <p id="output"></p><br><br>
<input type="button" onclick="buttonPressed()" value="submit" id="button"><br><br>

<script>

    function buttonPressed(){
        console.log("output 2")
        document.getElementById("output").innerHTML = "output 1"

        while (true){
            // doing something that takes a long time
        }

    }

    console.log("output 1")
    document.getElementById("output").innerHTML = "output 1"

</script>

upon pressing the button I would like the output to read "output 2" rather than having to wait for the button handler to finish. I have a while true in the button handler to demonstrate this, in reality I won't have a while true but rather some kind of process that takes a while. I would like to let the user know that this process has begun and that they should wait for it to finish.

Thanks for the help

Mathew
  • 1,116
  • 5
  • 27
  • 59
  • 1
    Don't block the browser thread. – SLaks Jan 02 '18 at 22:22
  • 1
    I don't know what that means – Mathew Jan 02 '18 at 22:22
  • why not just replace the `writeOutput` call with ```document.getElementById("output").innerHTML = "something"```? – lluisrojass Jan 02 '18 at 22:22
  • It is like that, i forgot to change it – Mathew Jan 02 '18 at 22:23
  • Possible duplicate of [Is it possible to 'thread' Javascript and keep access to the UI?](https://stackoverflow.com/questions/7909593/is-it-possible-to-thread-javascript-and-keep-access-to-the-ui) – PM 77-1 Jan 02 '18 at 22:26
  • What SLaks means is that if you have a long-running synchronous process (such as the while loop above) it will prevent all other javascript code from running until it has competed. So, for instance, if the user clicks on a drop-down menu, button, the menu will not open immediately. Whatever your long-running process is, you should make it asynchronous. – David Knipe Jan 02 '18 at 23:06

1 Answers1

2

The reason that your output is not showing is because the browser thread is busy with executing the current task (your function). As a result, the browser cannot redraw the page which would show the updated output.

In order to get around this, you need to use two separate tasks. One way to accomplish this would be to simply run your long running code in a timeout.

function buttonPressed(){
    console.log("output 2")
    writeOutput("output 2")

    setTimeout(function(){ //use a separate task and allow the page to draw
        while (true){
            // doing something that takes a long time
        }
    },4);
}

As a side note, 4 is used here because 4 milliseconds is generally the smallest time you can use for one timeout due to browser limitations and the html5 spec

Travis J
  • 81,153
  • 41
  • 202
  • 273
  • No, it will not. It will however start a separate **task**. In JavaScript, there is a task queue, and as a result in between the separate tasks sequentially executing, the browser will take a moment to redraw the screen from the previous trigger (innerHTML or whatever is modifying the page in your writeOutput). Here is the list of triggers: https://gist.github.com/paulirish/5d52fb081b3570c81e3a – Travis J Jan 02 '18 at 22:34