I want to refresh a span element before my calculations start to inform user that calculation was started.
the following code never displays 'calculating' message:
<script>
document.getElementById('text').innerHTML = 'calculating';
for (var i=0; i<9999;i++){
var y = Math.pow(i,i);
console.log(y);
}
document.getElementById('text').innerHTML = 'done';
</script>
</body>
</html>
how to fix that?
Guys, setTimeout is not an option for me. besides it looks ugly.
Place your code inside a setTimeout() call, and add a very minimal delay. I usually put 0ms, which just waits for the frame to render, then calls the function. Example:
document.getElementById('text').innerHTML = 'calculating';
setTimeout(function() {
for (var i=0; i<9999;i++){
var y = Math.pow(i,i);
console.log(y);
}
document.getElementById('text').innerHTML = 'done';
}, 0);
The first argument is a function to be called after the time passes, the second argument is the time to wait before calling the function. Note that this may still hang the browser if the calculation is too big (e.g. 999999 loop steps on a 2.5GHz i5)
Related
This might be a simple question but I have been searching for an answer to no avail. The code below is supposed to read five strings then update the page with these values, one value at a time. However, this worked only in Firefox (i.e. the document is updated after each iteration). Other browsers just showed the last value!! Anyone can help me understand this weird behavior?
<h1 id="test"></h1>
<script>
for(var i = 0; i<5; i++){
var x = window.prompt("Write something..");
document.getElementById("test").innerHTML = x;
}
</script>
Edit: Thanks everyone. setTimeout worked fine. what is the best alternative to window.prompt? Forms?
You have to give a chance for browser to do its job. When you are in a loop, you are occupying browser. Following example works in chrome:
<h1 id="test"></h1>
<script>
function askOne() {
var x = window.prompt("Write something..");
document.getElementById("test").innerHTML = x;
}
function ask() {
for(var i = 0; i<5; i++){
setTimeout(askOne, 0);
}
}
setTimeout(ask, 0);
</script>
With setTimeout(), you are giving a change to browser to do somethings. Which it may or may not use.
While it might be ok for some local test.html, in real life, one does not do it this way.
The old school way is to use setInterval or setTimeout.
function updatePage(x) {
// perform some change to the DOM, e.g.
document.getElementById("test").innerHTML = x;
}
// This will call updatePage(x) every 5000ms
setInterval(() => {updatePage(x)}, 5000);
Pretty sure this is deprecated though. And what you probably want to do is bind an event listener to the input element that x comes from.
I am new to javascript, and I am coding a game.
I would like to break out of the setInterval loop when a condition is met to display a game over screen. My code :
var timer = 0;
var i =0;
fond.onload= function()
{
timer = setInterval(boucle,50);
console.log("break");
}
function boucle()
{
i++;
if(i===4)
{
clearInterval(timer);
}
}
I never reach the break log because just after the clearInterval, the screen is stuck.
Thank you!
I am not sure what fond.onload represents in your code, but if you want the code to run when the page is loaded you should use window.onload or document.onload.
onload is a global event handler bound to all objects that gets executed when that object is loaded. I presume that in your case fond is never loaded as the rest of the code is fine, just never runs. It will run fine if you bind the function to window.onload.
You can read up more on that here
Consider the simplest case -- show progress bar, start computation, close progress bar.
With such html piece:
<p id="hello" style="display:none">HELLO WORLD</p>
To my surprise this does not work:
function foo()
{
var hello = $('#hello');
hello.html(new Date().getTime());
hello.show();
setTimeout(function(){
var big = 0;
for (var i=0;i<10000000;++i)
if (Math.sqrt(i)>Math.cos(i)) // just to keep CPU busy
big = i;
console.log(i);
},0);
}
$(window).load(function ()
{
foo();
});
And using jQuery promise does not help as well:
hello.show().promise().done(function(){...
In both cases the element is shown (visually) at the same time as you have the output in console.
I wrote visually, because internally the element can be reported as already shown, but what user sees counts.
You can put your code for computing in separate javascript function, even its linear it wont wait for computing to get finished in javascript and move to next line immediately. I have put a wait before hiding the progress bar because you need to have it available for atleast a second.
function startComputing(){
var big = 0;
for (var i=0;i<10000000;++i)
if (Math.sqrt(i)>Math.cos(i)) // just to keep CPU busy
big = i;
console.log(i);
}
function foo()
{
var hello = $('#hello');
hello.html(new Date().getTime());
hello.show();
setTimeout(function(){startComputing();},500);
setTimeout(function(){hello.hide()},1000);
}
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();
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);