Is setInterval handler called while my script running? - javascript

I planned to use setInterval to simply set a variable to false, which would be inspected by the main loop to stop. Example (note: this is an example only, the acutal code is not a while() loop which would be easy to reconstruct, but a quite complex, and long to execute script generated by a closed source software actually):
var running = true;
setInterval(function () {
if (running) {
console.log("Stopping now!");
running = false;
}
}, 100);
while (running) {
// do something ...
}
However it does not seem to work at least firefox drops a "busy script" box after a while. What's the problem with the code above? setInterval() may not be able to run if your script already runs otherwise? I couldn't find an exact specification what setInterval() does exactly.
I would need something like this, since I already have huge (and very long to execute) script, so I thought I will try to stop it after a while, then using setTimeout() to let the browser breath a bit and then continue: as the script itself does know its internal state so it can continue from any point, but it's not an option to modify the script actually ....
If it's not possible with setInterval, is there any alternative to this, without any modification in the "long to execute" code itself?
Thanks!

If it's not possible with setInterval, is there any alternative to this, without any modification in the "long to execute" code itself?
One possibility is to make that a web worker rather than trying to use it on the UI thread. Despite people repeatedly saying so, JavaScript is not single-threaded (JavaScript, the language, is silent on the subject), not even on browsers anymore. In the browser environment, there is one main UI thread, but you can spawn other worker threads (web workers). The worker(s) and the main UI code can communicate via postMessage / onmessage.
Here's an example of a web worker in action. This page uses JavaScript on the UI thread to start a web worker, which runs on a separate thread. The worker runs for 10 seconds, busily updating a counter (this is just to simulate a long-running, calculation-intensive process), and sends updates to the UI thread every second:
Main page:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Worker Example</title>
<style type="text/css">
body {
font-family: sans-serif;
}
</style>
<meta charset="UTF-8">
</head>
<body>
<script>
(function() {
var worker = new Worker("worker.js");
worker.onmessage = function(e) {
display("Worker says " + e.data);
};
display("Starting worker");
worker.postMessage("start");
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
})();
</script>
</body>
</html>
worker.js:
this.onmessage = function(e) {
var counter, lastUpdate, now;
if (e.data === "start") {
// Loop without yeilding for 10 seconds, sending updates
// to the UI every second.
start = lastUpdate = Date.now();
counter = 0;
do {
++counter;
now = Date.now();
if (now - lastUpdate > 1000) {
lastUpdate = now;
this.postMessage(counter);
}
}
while (now - start < 10000);
this.postMessage("Done");
}
};
(You're not required to make the worker wait for a message to start, but it's fairly common.)

The problem is that Javascript is single-threaded. Rewrite your while loop to use setInterval itself and everything should work, since you will release the thread at the end of each loop.

You should use setTimeout or setInterval instead while loop. JS runs in single thread, so infinite loop will freeze your browser.
var running = true;
setInterval(function(){
if(running){
console.log('Stopping now!');
running = false;
}
}, 100);
(function loop(){
// Do yours loop stuff
if( running ){
setTimeout(loop, 0);
}
})();

You should consider using Worker or writing asynchronous code.
Or you can modify your code.
var running = true;
var past = Date.now();
while (running) {
// do heavy calculations ...
if ((Date.now() - past) > 10) {
running = false;
}
}
Of course, blocking loops aren't good idea, but I don't see good way to satisfy requirement:
If it's not possible with setInterval, is there any alternative to this, without any modification in the "long to execute" code itself?

JavaScript runs in a single threaded event loop. What this means is while your code is running no other code can run. This is why your callback does not get executed.
You can workaround this by also making your while(running) be asynchronous. Consider doing the following:
var running = true;
var monitor = setInterval(function () {
if (running) {
console.log("Stopping now!");
running = false;
clearInterval(monitor);
}
}, 100);
var work = setInterval(function() {
if (running) {
// do something
} else {
clearInterval(work);
}
}, 1);
Don't forget to call clearInterval!

Related

slideshow in javascript using a thread [duplicate]

Is there some way to do multi-threading in JavaScript?
See http://caniuse.com/#search=worker for the most up-to-date support info.
The following was the state of support circa 2009.
The words you want to google for are JavaScript Worker Threads
Apart from from Gears there's nothing available right now, but there's plenty of talk about how to implement this so I guess watch this question as the answer will no doubt change in future.
Here's the relevant documentation for Gears: WorkerPool API
WHATWG has a Draft Recommendation for worker threads: Web Workers
And there's also Mozilla’s DOM Worker Threads
Update: June 2009, current state of browser support for JavaScript threads
Firefox 3.5 has web workers. Some demos of web workers, if you want to see them in action:
Simulated Annealing ("Try it" link)
Space Invaders (link at end of post)
MoonBat JavaScript Benchmark (first link)
The Gears plugin can also be installed in Firefox.
Safari 4, and the WebKit nightlies have worker threads:
JavaScript Ray Tracer
Chrome has Gears baked in, so it can do threads, although it requires a confirmation prompt from the user (and it uses a different API to web workers, although it will work in any browser with the Gears plugin installed):
Google Gears WorkerPool Demo (not a good example as it runs too fast to test in Chrome and Firefox, although IE runs it slow enough to see it blocking interaction)
IE8 and IE9 can only do threads with the Gears plugin installed
Different way to do multi-threading and Asynchronous in JavaScript
Before HTML5 JavaScript only allowed the execution of one thread per page.
There was some hacky way to simulate an asynchronous execution with Yield, setTimeout(), setInterval(), XMLHttpRequest or event handlers (see the end of this post for an example with yield and setTimeout()).
But with HTML5 we can now use Worker Threads to parallelize the execution of functions. Here is an example of use.
Real multi-threading
Multi-threading: JavaScript Worker Threads
HTML5 introduced Web Worker Threads (see: browsers compatibilities)
Note: IE9 and earlier versions do not support it.
These worker threads are JavaScript threads that run in background without affecting the performance of the page. For more information about Web Worker read the documentation or this tutorial.
Here is a simple example with 3 Web Worker threads that count to MAX_VALUE and show the current computed value in our page:
//As a worker normally take another JavaScript file to execute we convert the function in an URL: http://stackoverflow.com/a/16799132/2576706
function getScriptPath(foo){ return window.URL.createObjectURL(new Blob([foo.toString().match(/^\s*function\s*\(\s*\)\s*\{(([\s\S](?!\}$))*[\s\S])/)[1]],{type:'text/javascript'})); }
var MAX_VALUE = 10000;
/*
* Here are the workers
*/
//Worker 1
var worker1 = new Worker(getScriptPath(function(){
self.addEventListener('message', function(e) {
var value = 0;
while(value <= e.data){
self.postMessage(value);
value++;
}
}, false);
}));
//We add a listener to the worker to get the response and show it in the page
worker1.addEventListener('message', function(e) {
document.getElementById("result1").innerHTML = e.data;
}, false);
//Worker 2
var worker2 = new Worker(getScriptPath(function(){
self.addEventListener('message', function(e) {
var value = 0;
while(value <= e.data){
self.postMessage(value);
value++;
}
}, false);
}));
worker2.addEventListener('message', function(e) {
document.getElementById("result2").innerHTML = e.data;
}, false);
//Worker 3
var worker3 = new Worker(getScriptPath(function(){
self.addEventListener('message', function(e) {
var value = 0;
while(value <= e.data){
self.postMessage(value);
value++;
}
}, false);
}));
worker3.addEventListener('message', function(e) {
document.getElementById("result3").innerHTML = e.data;
}, false);
// Start and send data to our worker.
worker1.postMessage(MAX_VALUE);
worker2.postMessage(MAX_VALUE);
worker3.postMessage(MAX_VALUE);
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
We can see that the three threads are executed in concurrency and print their current value in the page. They don't freeze the page because they are executed in the background with separated threads.
Multi-threading: with multiple iframes
Another way to achieve this is to use multiple iframes, each one will execute a thread. We can give the iframe some parameters by the URL and the iframe can communicate with his parent in order to get the result and print it back (the iframe must be in the same domain).
This example doesn't work in all browsers! iframes usually run in the same thread/process as the main page (but Firefox and Chromium seem to handle it differently).
Since the code snippet does not support multiple HTML files, I will just provide the different codes here:
index.html:
//The 3 iframes containing the code (take the thread id in param)
<iframe id="threadFrame1" src="thread.html?id=1"></iframe>
<iframe id="threadFrame2" src="thread.html?id=2"></iframe>
<iframe id="threadFrame3" src="thread.html?id=3"></iframe>
//Divs that shows the result
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
<script>
//This function is called by each iframe
function threadResult(threadId, result) {
document.getElementById("result" + threadId).innerHTML = result;
}
</script>
thread.html:
//Get the parameters in the URL: http://stackoverflow.com/a/1099670/2576706
function getQueryParams(paramName) {
var qs = document.location.search.split('+').join(' ');
var params = {}, tokens, re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params[paramName];
}
//The thread code (get the id from the URL, we can pass other parameters as needed)
var MAX_VALUE = 100000;
(function thread() {
var threadId = getQueryParams('id');
for(var i=0; i<MAX_VALUE; i++){
parent.threadResult(threadId, i);
}
})();
Simulate multi-threading
Single-thread: emulate JavaScript concurrency with setTimeout()
The 'naive' way would be to execute the function setTimeout() one after the other like this:
setTimeout(function(){ /* Some tasks */ }, 0);
setTimeout(function(){ /* Some tasks */ }, 0);
[...]
But this method does not work because each task will be executed one after the other.
We can simulate asynchronous execution by calling the function recursively like this:
var MAX_VALUE = 10000;
function thread1(value, maxValue){
var me = this;
document.getElementById("result1").innerHTML = value;
value++;
//Continue execution
if(value<=maxValue)
setTimeout(function () { me.thread1(value, maxValue); }, 0);
}
function thread2(value, maxValue){
var me = this;
document.getElementById("result2").innerHTML = value;
value++;
if(value<=maxValue)
setTimeout(function () { me.thread2(value, maxValue); }, 0);
}
function thread3(value, maxValue){
var me = this;
document.getElementById("result3").innerHTML = value;
value++;
if(value<=maxValue)
setTimeout(function () { me.thread3(value, maxValue); }, 0);
}
thread1(0, MAX_VALUE);
thread2(0, MAX_VALUE);
thread3(0, MAX_VALUE);
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
As you can see this second method is very slow and freezes the browser because it uses the main thread to execute the functions.
Single-thread: emulate JavaScript concurrency with yield
Yield is a new feature in ECMAScript 6, it only works on the oldest version of Firefox and Chrome (in Chrome you need to enable Experimental JavaScript appearing in chrome://flags/#enable-javascript-harmony).
The yield keyword causes generator function execution to pause and the value of the expression following the yield keyword is returned to the generator's caller. It can be thought of as a generator-based version of the return keyword.
A generator allows you to suspend execution of a function and resume it later. A generator can be used to schedule your functions with a technique called trampolining.
Here is the example:
var MAX_VALUE = 10000;
Scheduler = {
_tasks: [],
add: function(func){
this._tasks.push(func);
},
start: function(){
var tasks = this._tasks;
var length = tasks.length;
while(length>0){
for(var i=0; i<length; i++){
var res = tasks[i].next();
if(res.done){
tasks.splice(i, 1);
length--;
i--;
}
}
}
}
}
function* updateUI(threadID, maxValue) {
var value = 0;
while(value<=maxValue){
yield document.getElementById("result" + threadID).innerHTML = value;
value++;
}
}
Scheduler.add(updateUI(1, MAX_VALUE));
Scheduler.add(updateUI(2, MAX_VALUE));
Scheduler.add(updateUI(3, MAX_VALUE));
Scheduler.start()
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
With the HTML5 "side-specs" no need to hack javascript anymore with setTimeout(), setInterval(), etc.
HTML5 & Friends introduces the javascript Web Workers specification. It is an API for running scripts asynchronously and independently.
Links to the specification and a tutorial.
There's no true threading in JavaScript. JavaScript being the malleable language that it is, does allow you to emulate some of it. Here is an example I came across the other day.
There is no true multi-threading in Javascript, but you can get asynchronous behavior using setTimeout() and asynchronous AJAX requests.
What exactly are you trying to accomplish?
Here is just a way to simulate multi-threading in Javascript
Now I am going to create 3 threads which will calculate numbers addition, numbers can be divided with 13 and numbers can be divided with 3 till 10000000000. And these 3 functions are not able to run in same time as what Concurrency means. But I will show you a trick that will make these functions run recursively in the same time : jsFiddle
This code belongs to me.
Body Part
<div class="div1">
<input type="button" value="start/stop" onclick="_thread1.control ? _thread1.stop() : _thread1.start();" /><span>Counting summation of numbers till 10000000000</span> = <span id="1">0</span>
</div>
<div class="div2">
<input type="button" value="start/stop" onclick="_thread2.control ? _thread2.stop() : _thread2.start();" /><span>Counting numbers can be divided with 13 till 10000000000</span> = <span id="2">0</span>
</div>
<div class="div3">
<input type="button" value="start/stop" onclick="_thread3.control ? _thread3.stop() : _thread3.start();" /><span>Counting numbers can be divided with 3 till 10000000000</span> = <span id="3">0</span>
</div>
Javascript Part
var _thread1 = {//This is my thread as object
control: false,//this is my control that will be used for start stop
value: 0, //stores my result
current: 0, //stores current number
func: function () { //this is my func that will run
if (this.control) { // checking for control to run
if (this.current < 10000000000) {
this.value += this.current;
document.getElementById("1").innerHTML = this.value;
this.current++;
}
}
setTimeout(function () { // And here is the trick! setTimeout is a king that will help us simulate threading in javascript
_thread1.func(); //You cannot use this.func() just try to call with your object name
}, 0);
},
start: function () {
this.control = true; //start function
},
stop: function () {
this.control = false; //stop function
},
init: function () {
setTimeout(function () {
_thread1.func(); // the first call of our thread
}, 0)
}
};
var _thread2 = {
control: false,
value: 0,
current: 0,
func: function () {
if (this.control) {
if (this.current % 13 == 0) {
this.value++;
}
this.current++;
document.getElementById("2").innerHTML = this.value;
}
setTimeout(function () {
_thread2.func();
}, 0);
},
start: function () {
this.control = true;
},
stop: function () {
this.control = false;
},
init: function () {
setTimeout(function () {
_thread2.func();
}, 0)
}
};
var _thread3 = {
control: false,
value: 0,
current: 0,
func: function () {
if (this.control) {
if (this.current % 3 == 0) {
this.value++;
}
this.current++;
document.getElementById("3").innerHTML = this.value;
}
setTimeout(function () {
_thread3.func();
}, 0);
},
start: function () {
this.control = true;
},
stop: function () {
this.control = false;
},
init: function () {
setTimeout(function () {
_thread3.func();
}, 0)
}
};
_thread1.init();
_thread2.init();
_thread3.init();
I hope this way will be helpful.
You could use Narrative JavaScript, a compiler that will transforms your code into a state machine, effectively allowing you to emulate threading. It does so by adding a "yielding" operator (notated as '->') to the language that allows you to write asynchronous code in a single, linear code block.
The new v8 engine which should come out today supports it (i think)
In raw Javascript, the best that you can do is using the few asynchronous calls (xmlhttprequest), but that's not really threading and very limited. Google Gears adds a number of APIs to the browser, some of which can be used for threading support.
If you can't or don't want to use any AJAX stuff, use an iframe or ten! ;) You can have processes running in iframes in parallel with the master page without worrying about cross browser comparable issues or syntax issues with dot net AJAX etc, and you can call the master page's JavaScript (including the JavaScript that it has imported) from an iframe.
E.g, in a parent iframe, to call egFunction() in the parent document once the iframe content has loaded (that's the asynchronous part)
parent.egFunction();
Dynamically generate the iframes too so the main html code is free from them if you want.
Another possible method is using an javascript interpreter in the javascript environment.
By creating multiple interpreters and controlling their execution from the main thread, you can simulate multi-threading with each thread running in its own environment.
The approach is somewhat similar to web workers, but you give the interpreter access to the browser global environment.
I made a small project to demonstrate this.
A more detailed explanation in this blog post.
Javascript doesn't have threads, but we do have workers.
Workers may be a good choice if you don't need shared objects.
Most browser implementations will actually spread workers across all cores allowing you to utilize all cores. You can see a demo of this here.
I have developed a library called task.js that makes this very easy to do.
task.js Simplified interface for getting CPU intensive code to run on all cores (node.js, and web)
A example would be
function blocking (exampleArgument) {
// block thread
}
// turn blocking pure function into a worker task
const blockingAsync = task.wrap(blocking);
// run task on a autoscaling worker pool
blockingAsync('exampleArgumentValue').then(result => {
// do something with result
});
With HTML5 specification you do not need to write too much JS for the same or find some hacks.
One of the feature introduced in HTML5 is Web Workers which is JavaScript running in the background,independently of other scripts, without affecting the performance of the page.
It is supported in almost all browsers :
Chrome - 4.0+
IE - 10.0+
Mozilla - 3.5+
Safari - 4.0+
Opera - 11.5+
Topaz is lock free Multithreaded Javascript Engine for .NET: https://github.com/koculu/topaz

javascript set interval run as separate thread?

I want to use a timer as a fallback in case I end up in an infinite loop. It seems that set interval is the right way to do this. However, it's not working for me.
From my research, it seems like setInterval should run in a separate thread in the background, but I don't see it.
Why is this behavior happening? And how do I solve this?
var time = 0;
window.setInterval(function(){time++;}, 1000);
while (true) {
//stuff done
if (time >= 5) {
break;
}
}
Browser javascript runs in a single thread. So if you perform something that takes too long - it will freeze browser.
See John Resig article for further details: http://ejohn.org/blog/how-javascript-timers-work/
After you read that article you'll get that your setInterval callback queued to be run in 1000ms after now but only after the current code is finished. It cannot finish though, because of the infinite loop.
zerkms has the correct answer. But I would add that web workers are a way to get some multi-threaded-ish behavior from client side javascript.
var worker = new Worker('my_task.js');
worker.onmessage = function(event) {
console.log("Called back by the worker!\n");
};
The worker runs in a background thread, and you can exchange messages and subscribe to events. It's pretty nifty.
As has been already said - the callback to setInterval doesn't run until the infinite loop finishes. To do what you are trying to achieve - without using web workers - you have to check the time from the loop itself:
var start = Date.now();
while((Date.now() - start) < 5000){
...
}

Adding text periodically

I am trying to run small snippet code in JavaScript, where I want to write on the web page simple hello world each 5 seconds. I think it must be ok, but no, still I got only first hello world and no more. Could you give me a hand in this? Thanks
<script type="text/javascript">
var i=0;
function startTimer() {
window.setTimeout('refresh()',5000);
}
function refresh() {
document.write("Hello world "+i+"<br/>");
i++;
window.setTimeout('startTimer()',1);
}
startTimer();
</script>
NOTE: As Amar Palsapure has noted in this answer, the root cause of the problem was the use of document.write. In my demonstration, I use a p element to document.body.appendChild() to add the text to the screen.
You can use setTimeout(), but you have to make it contingent on the last setTimeout() that ran; so that each time the caller runs, it creates the next timeout.
setInterval() is designed to run at a "regular" interval (neither setTimeout() nor setInterval() are truly reliable in when they run); however, if the calls to setInterval() get backed up due to some other process blocking it's execution (Javascript is single-threaded), you could have issues with those queued callbacks. That's why I prefer the approach I have below.
Note, refrain from the setTimeout('funcCalled()', 100) usage; this is running an eval() on that string you're passing in, which can change the scope in which you're running the callback, as well as being considered "evil" due to security issues related to eval(). You're best to avoid it altogether.
EDIT - Modified slightly.
I have made some changes to the approach. See my comments.
// The first and last lines comprise a self-executing,
// anonymous function, eg, (function(){})();.
// This allows me to use a local function scope and not the
// global window scope, while still maintaining my variables
// due to it being a "closure" (function(){}).
(function(){
var i = 0,
timer = 5000,
// I'm just going to add this to the DOM.
text = document.createElement('p');
// This is a variable function, meaning it stores a
// reference to a function.
var helloWorld = function() {
// Here is where I add the Hello World statement
text.innerHTML += 'Hello World! Loop: ' + i++ + '<br/>';
// Them add it to the DOM.
document.body.appendChild(text);
// I added this so it wouldn't run forever.
if (i < 100) {
// A setTimeout() will be added each time the last
// was run, as long as i < 100.
// Note how I handle the callback, which is the
// first argument in the function call.
setTimeout(helloWorld, timer);
}
// I added the change so it wouldn't take so long
// to see if was working.
timer = 500;
}
// Here I use a variable function and attach it to the
// onload page event, so it will run when the page is
// done loading.
window.onload = helloWorld;
})();
http://jsfiddle.net/tXFrf/2/
The main issue is document.write. There is nothing wrong with setTimeout or rest of the code.
The reason it does not work is that once document.write is called the first time, it overwrites your existing code of setTimeout() and since there is no code so it will not work.
What you need to do is use some other means to write the value in the page, certainly no document.write...
Instead of using setInterval use setTimeout.
You can try this
<html>
<body>
<div id="clock" ></div>
<script type="text/javascript">
var i = 0,
timerHandle,
clock;
function startTimer() {
clock = document.getElementById('clock');
//You can use timerHandle, to stop timer by doing clearInterval(timerHandle)
timerHandle = self.setInterval(funRefresh, 2000);
}
var funRefresh = function refresh() {
clock.innerHTML += "Hello world " + i++ + "<br/>";
}
startTimer();
</script>
</body>
</html>
Hope this helps you.
Here is the working Code
var i = 0;
function startTimer() {
window.setInterval(refresh, 5000);
}
function refresh() {
document.write("Hello world " + i + "<br/>");
i++;
// window.setTimeout(startTimer,1);
}
startTimer();​

How many timers in a window? [duplicate]

I have to use atleast 2 setTimeouts and 1 setInterval. Does this have any dependency on the browser or javascript engine being used?
tl;dr: Don't worry about the cost of timers until you're creating 100K's of them.
I just did a quick test of timer performance by creating this test file (creates 100K timers over and over):
<script>
var n = 0; // Counter used to verify all timers fire
function makeTimers() {
var start = Date.now();
for (var i = 0; i < 100000; i++, n++) {
setTimeout(hello, 5000);
}
console.log('Timers made in', Date.now() - start, 'msecs');
}
function hello() {
if (--n == 0) {
console.log('All timers fired');
makeTimers(); // Do it again!
}
}
setTimeout(makeTimers, 10000); // Wait a bit before starting test
</script>
I opened this file in Google Chrome (v54) on my circa ~2014 Macbook Pro, and went to the Timeline tab in Developer Tools and recorded the memory profile as the page loaded and ran thru 3-4 cycles of the test.
Observations
The timer creation loop takes 200ms. The page heap size starts at 3.5MB pre-test, and levels out at 3.9MB.
Conclusion
Each timer takes ~.002 msecs to set up, and adds about 35 bytes to the JS heap.
On a page you can have as many setTimeouts/setIntervals running at once as you wish, however in order to control each individually you will need to assign them to a variable.
var interval_1 = setInterval("callFunc1();",2000);
var interval_2 = setInterval("callFunc2();",1000);
clearInterval(interval_1);
The same code above applies to setTimeout, simply replacing the wording.
As Kevin has stated, JavaScript is indeed single threaded, so while you can have multiple timers ticking at once, only one can fire at any one time - i.e. if you have one that fires a function which 'halts' in execution, for example with an alert box, then that JS must be 'resumed' before another can trigger I believe.
One further example is given below. While the markup is not valid, it shows how timeouts work.
<html>
<body>
<script type="text/javascript">
function addThing(){
var newEle = document.createElement("div");
newEle.innerHTML = "Timer1 Tick";
document.body.appendChild(newEle);
}
var t1= setInterval("addThing();",1000);
var t2 = setInterval("alert('moo');",2000);
</script>
</body>
</html>
You can use as many as you want. Just remember that JavaScript is single threaded, so none of them can execute in parallel.
var interval_1 = setInterval("callFunc1();",2000); calls eval() which is evil so it's BAD.
Use this instead var interval_1 = setInterval(callFunc1,2000);
And for the question, you may use as many as you want but if all have the same interval between two actions, you better do it this way
var interval = setInterval(function() {
// function1
fct1();
// function2
fct2();
},2000);

DOM style change waiting for pause

When this function is called, the style change on the "gif" element does not show up until "lotsOfProcessing()" finishes. However, when I uncomment the alert("test"), the style change is shown before the alert pops up.
What I am trying to do is have an animated gif displayed while lotsOfProcessing is running. This seemed pretty straight forward solution but it is clearly not working. Any suggestions / solutions?
function nameOfFuntion()
{
document.getElementById("gif").style.display = "inline";
//alert("test");
lotsOfProcessing();
}
JavaScript code executes on the same thread as the browser's rendering. Everything that needs to be drawn waits for JavaScript execution to complete - including the next frame of any GIF animation.
The only solution is to break your long processing code down into smaller parts and delay each part using timers.
For example:
function nameOfFuntion() {
document.getElementById("gif").style.display = "inline";
//alert("test");
lotsOfProcessing();
}
function lotsOfProcessing() {
var i = 0;
window.setTimeout(function () {
partOfIntenseProcessing();
if (i < 1000000)
i++, window.setTimeout(arguments.callee, 10);
}, 10);
}
This will delay how long it will take for your processing to complete, but between timer execution the GIF can continue to animate.
You can also take a look at Web Workers, which allow you to run JavaScript operations in a background thread. However, they are not widely implemented yet (read: not available in Internet Explorer).
Perform your heavy processing in a delayed function with window.setTimeout():
function nameOfFunction()
{
document.getElementById("gif").style.display = "inline";
window.setTimeout(lotsOfProcessing, 10);
}
That's strange indeed. Seems like lotsOfProcessing gets javascript's single thread before the dom has time to refresh, but it's the first time I hear of something like that.
You might try this (not that is not an ideal solution):
function nameOfFuntion()
{
document.getElementById("gif").style.display = "inline";
setTimeout(lotsOfProcessing, 100);
}
This is a vaguely educated guess but it may be worth trying to put document.getElementById("gif").style.display = "inline"; into a function eg.
function nameOfFuntion()
{
showGif();
//alert("test");
lotsOfProcessing();
}
function showGif() {
document.getElementById("gif").style.display = "inline";
}
My thinking is that perhaps the lotsOfProcessing() is getting hoisted to the top of nameOfFunction() because it's a function and therefore getting processed first.

Categories

Resources