Reputation: 47
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
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
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.
<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