Enric
Enric

Reputation: 47

How can I continue to play my GIF during JavaScript processing (as it freezes)?

My GIF image freezes after 5 seconds while my JavaScript code is doing some work. It unfreezes when procesing is finished.

Is there a solution to animate my GIF while the code is executing?

Here's my JavaScript code:

var play = function() {
    var image = document.getElementById('img');
    image.style.display="block";

    window.setTimeout(function(){
        for ( var i =0; i < 2000000000; i++ )
        {
            //Do nothing, in example
        }
    }, 5000);
};

var stop = function() {
    var image = document.getElementById('img');
    image.style.display="none";
};

HTML code:

<img id="img" src="loader.gif" style="display: none;"/>
<button id="Start" onclick="play()">Play</button>
<button id="Stop" onclick="stop()">Stop</button>

Upvotes: 1

Views: 2286

Answers (2)

www-0av-Com
www-0av-Com

Reputation: 735

Use yield as in this working example with minor mod's to your own code...

var play = function() {
//'-----------------------------------Insert Handler..
      var obj = myfuncGen.next(); //'start it
      if (obj.done == false) {
          setTimeout(play, 150); //'adjust for the amount of time you wish to yield (depends how much screen drawing is required or etc)
      } 
  }
  var myfuncGen = myfuncSurrogate(); //'creates a "Generator" out of next. 
  function* myfuncSurrogate() { //'This the original function repackaged! Note asterisk. 
//'-------------------------------------End Insert
  var image = document.getElementById('img');
    image.style.display="block";

    //window.setTimeout(function(){
        console.log("start");
        for ( var i =0; i < 20000000; i++ )
        {
          if ((i % 1000000) == 0) { //a yield set to go off every 1,000,000 loops (if the yield is called too often it will needlessly slowe down yor loop)
            console.log("yielding ", i / 1000000);
            yield;
          }
        }
        console.log("done");
    //}, 500);
};

play()
<img id='img' src='http://bestanimations.com/Earth&Space/Earth/earth-spinning-rotating-animation-52.gif' />

..I had to edit out window.setTimeout() as it created a detached function which causes an error with Yield. To restore your original intent, I would call play() from such a timeout.

If the link becomes broken to the random gif I chose, I am sure you could substitute another :-).

Upvotes: 0

faby
faby

Reputation: 7558

I think that in this case you should use webworker elements. They allow you to do some asynchronous operation in the background of the UI elements.

One example

<p>Value passed by the worker: <output id="result"></output></p>
<script>
    var worker = new Worker('worker.js');

    worker.onmessage = function (event) {
        document.getElementById('result').textContent = event.data;
    };
</script>

In a separate file (worker.js):

var n = 1;
search: while (true) {
    n += 1;

    for (var i = 2; i <= Math.sqrt(n); i += 1)
        if (n % i == 0)
            continue search;

    // Found a prime!
    postMessage(n);
}

Every time that you call postMessage you send some data from the background (that fires onmessage event of the worker element ) to the main thread.

Have a look at Using jQuery UI progress bar with MVVM, Knockout and web workers for your case:

In this post I would like to explore:

  • How to use the jQuery UI progress bar with KnockoutJS and MVVM pattern, as a simple example of reusing existing JavaScript UI components.
  • How to use web workers to execute long running task asynchronously and notify view model about the results and progress.

Upvotes: 4

Related Questions