How do I have two separate functions run simultaneously? If I wanted two clocks, one to count up and the other to count down, and I wanted them to run at the same time, how would I do it?
If I just did:
var up = 1;
while(true){
document.write(up);
up++;
if(up==11)
up=1;
}
var down = 10;
while(true){
document.write(down);
down--;
if(down==0)
down=10;
}
...it would just keep counting up...
Javascript is single threaded. There is only one thread that can ever access the page.
It is possible in some HTML5 browsers to use Web Workers to execute some code in another thread and then communicate with the main thread via messaging, but the Web Worker thread cannot access the DOM in any way.
If you want counters to run in a loop, the typical way of doing that is by using timers and then setting the contents of an object in the DOM each time the timer goes. In this way, you can appear to have multiple things running at the same time, but in reality, they are still one at a time, just separately timed.
Here's an example of two counters that "appear" to be running at the same time: http://jsfiddle.net/jfriend00/3yc9r/.
The code for that is this (run after the page is loaded):
var cntr1 = 1;
var cntr2 = 2;
setInterval(function() {
document.getElementById("time1").innerHTML = cntr1 += 13;
}, 33);
setInterval(function() {
document.getElementById("time2").innerHTML = cntr2 += 5;
}, 44);
Also, you really don't want to be doing document.write() in a loop. Code that's going to run for awhile should run after the page is loaded and should modify objects in the DOM directly rather than use document.write().
You would have to put both counters in the same loop, but JavaScript is inherently single threaded, your code example would freeze the browser. Try using the SetTimeout or SetInterval function to fire an event at a specific interval. http://www.w3schools.com/js/js_timing.asp
You don't. Javascript is single threaded. If you wanted a clock you would use asynchrounous timeouts.
// Counts up and down by one per second.
var up = 1;
setTimeout(function() {
up++;
document.write(up);
}, 1000);
var down = 10;
setTimeout(function() {
down--;
document.write(down);
}, 1000);
JS can only ever do one thing at a time (meaning in one single threaded run loop), but it supports lacing asynchronous callbacks together very very well.
You can't, and if you write to the body in a loop, it will be slow.
Instead use setTimeout() to run the next iteration of a forever loop. https://developer.mozilla.org/en/window.setTimeout
Related
I'm making an website game which uses many document.getElementById inside a setInterval that runs every 0.25 sec. This makes my webbsite slow after some time. I'm quite new to Javascript but I wonder if there's a more effective or efficient way to call and update a HTML element or create a effective loop that includes game latency and runs every 1 sec?
Precache all ID's.
Something in the lines of (pseudo code):
var all_objects = [];
...
onCreateObject = function(){
all_objects.push(newObject.id)
}
and then just iterate through the all_objects variable.
As for the loop itself, there are solutions out there already: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
set variables outside (above) your setInterval function:
var myDiv = document.getElementById("ID");
and then call them inside the setInterval function:
myDiv.something()
I wondered how many times can a JavaScript while statement (in Chrome's console) can increment a variable in a millisecond, so I quickly wrote this snippet directly into console:
var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }
The problem is that it runs forever.
Why is this happening, and how can I solve it?
This comes back to the one-threaded nature of JavaScript1. What happens is pretty much this:
Your variables are assigned.
You schedule a function, to set run = false. This is scheduled to be run after the current function is run (or whatever else is currently active).
You have your endless loop and stay inside the current function.
After your endless loop (never), the setTimeout() callback will be executed and run=false.
As you can see, a setTimeout() approach wont work here. You might work around that by checking the time in the while condition, but this will tamper with your actual measurement.
1 At least for more practical purposes you can see it as single-threaded. Actually there is an so called "event-loop". In that loop all functions get queued until they are executed. If you queue up a new function, it is put at the respective position inside that queue. After the current function has finished, the engine takes the next function from the queue (with respect to timings as introduced, e.g., by setTimeout() and executes it.
As a result at every point in time just one function is executed, thus making the execution pretty much single threaded. There are some exceptions for events, which are discussed in the link below.
For reference:
https://stackoverflow.com/a/16757582/1169798
Here a similar scenario was explained in more detail
https://stackoverflow.com/a/2734311/1169798
A more in-depth description on when JS can be seen as single-threaded and when not.
JavaScript is single-threaded so, while you are in the loop, nothing else gets executed.
To keep the true speed of Chrome without having to constantly retrieve the time to calculate speed, you could try this JS code:
var start = new Date().getTime()
var i = 0
while(i<1000000)
{
i++
}
var end = new Date().getTime()
var delta = end-start
var speed = i/delta
console.log(speed + " loops per millisecond")
Javascript is single-threaded, that mean it runs only one instruction at a time, sequentially.
The event system, like in many other languages and library, is handle by an event loop. The event loop is basically a loop, which on each iteration check for message in the queue, and dispatch events.
In javascript (as in mot of languages implementing this pattern), the event loop is called when the stack is empty, that is to say, when all functions have returns, in other word, at the end of the program code.
Your "real" program look something like this behind the scene :
var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }
while(true) {
/*
* check for new messages in the queue and dispatch
* events if there are some
*/
processEvents();
}
So the message from the clock saying timeout is over is never processed.
More info on the event loop on :
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop
Of course it is a bit more complex, check here those examples : Is JavaScript guaranteed to be single-threaded? (tl;dr: In some browser engines, some external events are not dependent on the event loop and are immediately fired when they occur, preempting the current task. But this is not the case with setTimeout, which just add a message to the queue and never fires immediately.)
The While loop doesn't access the setTimeout. You have code that sets run true, and then it will never become false.
JavaScript has single thread and has single-threaded anywhere.
I think this question in good:
Is JavaScript guaranteed to be single-threaded?
When your code is in loop other ocde not execute and block.
I've been reading John Resig's "Secrets of a JavaScript Ninja" and it explains that JavaScript is single-threaded. However, I tried testing this and I'm not sure what to take away from here:
// executing this in browser
(function () {
// throw something into event queue
setTimeout(function () {
alert("This will be called back after 1 second.");
}, 1000);
// arbitrary loop to take up some time
for (var i = 0; i < 10000; i += 1) {
console.log(i);
}
})();
Maybe I'm not understanding exactly what being single-threaded means, but I thought that the setTimeout callback wouldn't execute until all of the outer anonymous function is complete. However, running this in the browser shows that the callback function gets called while i's are still being outputted onto the console. To me, this seems like there's 2 threads with anonymous function's invokation occupying 1 thread and then the callback using the 2nd thread.
Can someone help un-confuse me?
console.log() is a weird function in some browsers (like Chrome) and is not synchronous itself so you can't really use it to gauge the single threadedness. What you are probably seeing is that the JS engine executes all the console.log() statements and then the setTimeout() runs to show the alert and, in parallel (in some other process that isn't javascript) all the data is being shown in the console.
Javascript is indeed single threaded. In your example, the setTimeout() callback will not execute until your for loop is done.
You can illustrate it better like this:
(function () {
// throw something into event queue
setTimeout(function () {
alert("This will be called back after 1 second.");
}, 1000);
function now() {
return new Date().getTime();
}
var start = now();
// loop for 1.2 seconds
while (now() - start < 1200) {}
alert("Looping done");
})();
Working jsFiddle demo: http://jsfiddle.net/jfriend00/3sBTb/
This is a bit of a tricky concept to understand. Throwing in things like event listeners also further muddies up the picture.
A simple way to think of it is as if you have a conveyor belt. You have your normal function calls all evenly spaced out, with room in between.
Things that are asynchronous things (timeouts, triggered events, etc.) fill those spots. There isn't an infinite amount of room between each of those normal calls, so it fits what it can from this queue, does a little more of the normal synchronized functions, fills some more space with asynchronous, etc.
The affect appears to be somewhat multi-threaded (and indeed you can cause race conditions of a sort with asynchronous calls). In many cases, the distinction doesn't matter. However, it is important to remember this.
However, when you try to debug things, especially when using tools like Chrome's console.log, it can look like things are scrambled because console.log itself is asynchronous (if it were synchronous, it would freeze your script on a long function).
You can see this yourself if you output something like this:
var input = document.createElement('input');
input.setAttribute('value', 0);
function inc() {
input.setAttribute('value', parseInt(input.getAttribute('value'))+1);
console.log(input);
if (parseInt(input.getAttribute('value')) < 100) {
setTimeout(inc, 10);
}
}
inc();
JSFiddle: http://jsfiddle.net/c2PnP/
What this script does it creates an input element, then every 10 milliseconds, it increments the value of input, then outputs the input element. It repeats 100 times (until value = 100).
If you look at your console, you'll notice that some of the values will be duplicated, it won't be a smooth progression. For example, on a run I just did, I see 5 inputs with a value of "100" and gaps for the missing numbers. This is because console.log is running asynchronously and only outputting when it gets the gap to do so.
(Note: If you have a super fast computer, you may need to decrease the time to something smaller, like 1, and/or increase the number of iterations to a bigger number).
John Resig covered this well. Summarizing:
"JavaScript can only ever execute one piece of code at a time (due to
its single-threaded nature)... when an asynchronous event occurs (like
a mouse click, a timer firing, or an XMLHttpRequest completing) it
gets queued up to be executed later.... After the initial block of
JavaScript finishes executing the browser immediately asks the
question: What is waiting to be executed? The browser then picks one
and executes it immediately. The [rest] will wait until the next
possible time, in order to execute."
I'm having a hard time understanding the logic behind the setTimer method in javascript.
<html><head>
<script>
function Timer () {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
document.getElementById('show').innerHTML=h+":"+m+":"+s;
t = setTimeout("Timer()", 1000);
}
</script>
</head>
<body onload="Timer()">
<div id="show"></div>
</body></html>
setTimeout is used to delay a function/method execution. Then why it is being used in a real-time clock?
t = setTimeout("Timer()", 1000);
This part is confusing.
The clock is recursively calling itself, after the elapsed period of time.
Making a real-time clock is impossible in JS.
Because of how JS engines work, if you put Timer in a loop, to run for an infinite period of time, you'd never see the time update on the screen (as changes aren't drawn to the window until a function finishes and there's a gap in the program).
Also, inside that infinite-loop, it would be impossible to do anything else with the page (even closing it), because JS can only do one thing at a time, so it can't listen to any of the user's clicking until it's done with this loop.......
So that's what the setTimeout is for.
Timer is the function which acts as the clock.
Inside of the Timer function, at the end when all of the work is done, it's telling setTimeout to wait 1 second (1000ms) and then to call a function called Timer.
Timer just so happens to be the same function. But setTimeout doesn't know that, and doesn't care.
The t in this case is largely useless. setTimeout will return a number -- like taking a number at the doctor's office.
If, before you go through with it, you decide to back out, you can call clearTimeout(t); and it'll skip over that call (in this case, it would stop calling the clock).
There are a few bad-practices in here, that I figure I should mention, so that you can try not to copy them in your own practice.
First:
Pass setTimeout a reference to a function, and not a string...
var runThisFunction = function () { console.log("It's the future!"); },
time_to_wait = 250;
// DON'T DO THIS
setTimeout( "runThisFunction()", 250 );
// DO THIS
setTimeout( runThisFunction, 250 );
The difference is that setTimeout will run that string through eval, which can be a huge security concern depending on what you're trying to do.
The second problem is setting a random global variable, t... ...and hoping to use that as a solution.
First, in a couple of years, JS engines are going to start yelling at people for doing that stuff. Second, it's a huge hole, because any part of any app on that page could then overwrite t, or you could be relying on t somewhere else in your script, but every 1000ms, it gets written over with a new number.
Instead, they probably should have used a Timer.start(); and Timer.stop(); setup.
Your code:
t = setTimeout("Timer()", 1000);
The first thing you should know is that it's considered bad practice to put the first parameter in a string -- it should be the function name, unquoted, and without brackets, like so:
t = setTimeout(Timer, 1000);
That aside, your question about why it's being used to display a clock:
The use of setTimeout() inside the Timer() function to call itself is a common Javascript pattern to get a function to be called repeatedly. setTimeout() itself only triggers the function to be called a single time, after the given period of time has elapsed, so for a repeating event it needs to be re-triggered every time.
Since the setTimeout call is inside the Timer() function, it won't be set until Timer() is called the first time by some other means. This is where the body onload comes in.
As you suspect, setTimeout() isn't an accurate method for guaranteeing that a function will be called after exactly a given amount of time. Javascript is not multi-threaded, so any event handlers that are triggered must wait for any other code that is running at the same time. If something else is running slowly, this may cause your timer not to be triggered at exactly the moment it wants to be.
However, this isn't really a problem for your clock , because the clock is setting itself to the actual system time rather than relying on the setTimeout loop to keep itself in sync; the setTimeout loop is simply being used to make sure the display is updated (approximately) once a second. If it isn't actually quite exactly once a second, it doesn't really matter.
I hope that helps explain things a bit better.
When the Timer() function is called, it schedules itself to be run again one second later. The end result is once every second, Timer() updates the show element with the current time. (I have no idea why it's assigned to t, unless t is used in some other code on the page.)
The line starts The function again after one second.
When my extension starts a heavy job (a for loop which will trigger more processes down the road), Firefox stops responding. It won't resume to work until my extension completes the job.
My extension takes around 16000 milliseconds to complete its work. Is there a way to execute my script asynchronously? Or Is there any other way to resolve this issue?
TL;DR: Yes, there is a way. Make your code run in short iterations and yield using setTimeout.
There's no such thing as threads in JavaScript. Okay, yes, there is the Worker API. But I still think threads are unnecessary and evil (race conditions, deadlocks, etc. – it has all been covered before). Browser Extensions may be the only use case where threads in JavaScript could have any merit. But it's still best avoided.
So. If not threads, what then? JavaScript has an event loop, which is a curse and a blessing. Every time a piece of your code runs, all other things on the page are halted (that's why the page becomes unresponsive). To prevent this from happening, you should make each piece of your code run as fast as possible and then yield to other events in the event queue.
To do this, replace your for loop with a recursive function that calls itself via setTimeout. So instead of this:
var length = collection.length; // <-- 2 gazillion
var i;
for (i=0; i<length; i+=1) {
lengthyOperation(i);
}
// Script yields here.
... you'll do something like this:
var length = collection.length; // <-- still 2 gazillion
var i;
function lengthyOperationAsync() {
lengthyOperation(i); // <-- still lengthy
i += 1;
if (i < length) {
setTimeout(lengthyOperationAsync, 0);
}
// Script yields here.
}
This way, the browser can update the page and handle user input in between iterations of your lengthy for loop. There is only one drawback: it may take longer than usual in some browsers. This is because timer resolution; some browsers have a minimum delay of 4ms when using setTimeout, even if you specify 0.
By the way, there is a proposal for a function called setImmediate, which is meant for this exact purpose – but most browsers haven't implemented it yet.