I'm trying to implement something that looks like a console window, but on a webpage. I'd like it to just write a new line pinging an API every second or so. I have:
for (i = 0; i < 5; i++) {
text = httpGet('APICALL' );
document.write(text + '<br>');
sleep(1000);
}
This however, runs ALL the calls first and then writes. How can I change this?
EDIT:
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
You should use something like setTimeout, which is a standard way of doing it:
var sleepTime = 1000;
var i = 0;
setTimeout(function readNextMessage() {
if (i < 5) {
text = httpGet('https://turbine-farm.run.aws-usw02-pr.ice.predix.io/api/turbines/1/heartbeat' );
document.body.innerHTML += text + '<br>';
}
i += 1;
setTimeout(readNextMessage, sleepTime);
}, sleepTime);
You cant sleep a webpage. Your sleep function is doing this:
Enters into a loop of 1e7 steps.
Each step does a difference and compares it to a number.
It breaks if comparison is true.
Those 3 steeps, in a modern computer, are done in less than a second.
Related
I want to make the code bellow to calculate the time it takes to run the loop, but somehow none of the things I have tried worked!
I have tried using date, but it provides really inaccurate timing.
I have tried using another interval to check if an element already exists, and some similar solutions, etc, but the result is always the same, Javascript always checks things before the loop finishes!
var t = 0;
function myStartFunction() {
myVar = setInterval(function() {
t++;
document.getElementById("tempo").innerHTML = "Elapsed time: " + t + " segundos";
}, 1000);
}
myStartFunction();
function myStopFunction() {
clearInterval(myVar);
}
var n = "";
var i = 0;
while (i < 100000) {
n += "<br>" + i;
i++;
if (i == 100000) {
///////////////////clearInterval(myVar);
}
}
document.getElementById("range").innerHTML = n;
<!DOCTYPE html>
<html>
<body>
<h2 style="font-family:arial">TIME TO RUN LOOP</h2>
<hr> <br>
<button onclick="myStopFunction()">STOP</button> <br>
<p id="tempo" style='font-family:arial'>Elapsed time: 0 segundos</p>
<p id="range" style='font-family:arial'></p>
</body>
</html>
The best answer would be one that would provide an elapsed time in the following format: 00:00:00:0000
... without the need of a button!
And with a working clearInterval(myVar); where currently there is a Javascript comment.
use performance (see MDN). Or check this jsFiddle
let t = 0;
let start = performance.now();
let padZero = (v, n = 2) => `${v}`.padStart(n, "0");
let toTime = v =>
`elapsed (hh:mm:ss:ms) ${
padZero(Math.floor(v/(60*60000)))}:${
padZero(Math.floor(v/60000))}:${
padZero(Math.floor(v/1000))}:${
padZero(Math.floor(v%1000), 3)}`;
myStartFunction();
function myStartFunction() {
if (performance.now() > 10000) {
return console.log(`${toTime(performance.now() - start)} END`);
}
console.log(toTime(performance.now() - start));
setTimeout(myStartFunction, 1000);
}
.as-console-wrapper { top: 0; max-height: 100% !important; }
Updated: I made this in the correct format with KooiInc code and changed out Date.Time for performance.now().
I changed your code a bit, this should calculate the time correctly for your while loop. Comment out the rest of your JavaScript code and put this code in your script.
I don't understand what you need for the ClearIntervalFunction exactly, but I can help you create that function if you give me more details on what you need.
function loop() {
let n = "";
let i = 0;
while (i < 100000)
{
n += "<br>" + i;
i++;
}
return n;
}
function segundoFormatter(segundo) {
let zeros = 8;
let segundoArray = segundo.toString().split(".");
let number2Add = zeros - segundoArray[0].length;
let STR = "";
for(let i = 0; i < number2Add; i++){
STR += "0";
if(i == 1 || i == 3 || i == 5){
STR += ":";
}
}
let finalStr = STR + segundoArray[0] + segundoArray[1];
return finalStr.toString().substring(0,13);
}
window.onload = function(){
let startTime = performance.now()
let n = loop();
let endTime = performance.now()
let timeLoopTakes = (endTime - startTime);//00:00:00:0000
// segundoFormatter(timeLoopTakes);
document.getElementById("tempo").innerHTML = "Elapsed time: " +
segundoFormatter(timeLoopTakes) + " segundos";
//You can uncomment this line belowand get like 10000 things in your dom
//document.getElementById("range").innerHTML = n;
}
You can use the getTime() function of the Date object to get the UNIX timestamp associated with the current time.
let initialTime = new Date().getTime();
for(let i = 0; i < 100000000; i ++) {
// do something
}
let finalTime = new Date().getTime();
console.log ('this took : ' + (finalTime - initialTime) + ' milliseconds' );
This question already has answers here:
Javascript wait() function [closed]
(2 answers)
Closed 3 years ago.
I am running a for loop with a break of 1 second between each iteration:
<html>
<body>
<script>
var text = "";
var i;
// Wait function
function wait(ms){
var start = new Date().getTime();
var end = start;
while(end < start + ms) {
end = new Date().getTime();
}
}
for (i = 0; i < 5; i++) {
text += "The number is " + i + "<br>";
wait(100)
}
</script>
<script>document.write(text)</script>
</body>
Currently, when I open the file in a web browser, the browser window is loading until the for loop has finished and then the results are displayed (five output lines). Is there a way to display the out put "as it happens". With this I mean, I open the page and every second a new line is printed.
Thank you!
You should learn about timeout and interval concepts in Javascript.
Here is code that will do the work. Examine it.
<html>
<body>
<script>
function waitAndWrite(num) {
setTimeout(() => {
let text = "The number is " + num + "<br>";
document.write(text)
}, num * 1000)
}
for (let i = 0; i < 5; i++) {
waitAndWrite(i)
}
</script>
</body>
Instead of using your own "wait" function, you could use setInterval(fn, timeout) src instead.
var i = 0;
var interval = setInterval(() => {
i = i + 1;
if(i === 5) {
clearInterval(interval);
}
document.write("Your text " + i);
}, 1000);
What you are trying to achieve manually, you can achieve the same with WindowOrWorkerGlobalScope.setTimeout():
The setTimeout() method of the WindowOrWorkerGlobalScope mixin (and successor to Window.setTimeout()) sets a timer which executes a function or specified piece of code once the timer expires.
for (let i = 0; i < 5; i++) {
setTimeout(() => document.write("The number is " + i + "<br>"), 1000 * i); // multiply the delay with i in each iteration
}
Hi I am trying to get an image to blink using the code below by changing the image. Is there something wrong with my "setTimeout"? TIA
var Test = new Array();
Test.length = 2;
for (var i = 0; i < Test.length; i++) {
Test[i] = new Image();
Test[i].src = "images/Image2" + (i+1) + ".png";
}
function ChangeImage() {
for (var i = 0; i < Test.length; i++) {
document.getElementById('Test_Image').src = Test[i].src;
}
setTimeout("ChangeImage()", 1000);
}
ChangeImage();
First.. you complicated yourself with the new Image() part. You could just use Test[i] = "images/Image2" + (i+1) + ".png";
And for your code, firstly you change the images really fast once every 1 second.
It should be something like this:
function ChangeImage() {
for (var i = 0; i < Test.length; i++) {
setTimeout(function(){document.getElementById('Test_Image').src = Test[i];
}, (i+1) *1000);
}
if(play){
setTimeout("ChangeImage()", Test.length * 1000);
}
}
This will not halt the javascript code at any point.
After 1 sec it will put image21, after 2 seconds image21 and it will call itself again and it will start all over again;
I put the variable play so you could stop the animation if you wanted.
setTimeout() is not blocking. That means it only schedules an activity to happen some time in the future and the rest of your Javascript just keeps running. So, you were scheduling Test.length setTimeout() all for the exact same time 1 second from now. Instead, you need to schedule the next image change and then, when that timer fires, you schedule the one after that and so on.
If you just want to cycle through the various images one second apart, you can do this:
function ChangeImage() {
var cntr = 0;
function next() {
if (cntr < Test.length) {
document.getElementById('Test_Image').src = Test[cntr++].src;
// after changing src, schedule next change for 1 second from now
setTimeout(next, 1000);
}
}
// start first iteration
next();
}
ChangeImage();
You may also need to make sure that all your images are properly preloaded so they display immediately when you set their source. There are numerous ways to make sure the preload is done before starting the rotation such as these:
Image preloader javascript that supports events
How do you cache an image in Javascript
Try something like this.
Edit: Accidentally put setTimeout instead of setInterval. Thanks Santi for point that out.
var Test = new Array();
Test.length = 2;
for (var i = 0; i < Test.length; i++) {
Test[i] = new Image();
Test[i].src = "images/Image2" + (i+1) + ".png";
}
var count = 0;
function ChangeImage() {
if (count >= Test.length)
count = 0;
document.getElementById('Test_Image').src = Test[count].src;
count++;
}
setInterval(ChangeImage, 1000);
Your for loop switches the src once and immediately switches it back, so you can't see it change. Try this instead:
var Test = [];
for (var i = 0; i < 2; i++) {
Test.push("images/Image2" + (i+1) + ".png");
};
var x = 0;
document.getElementById('Test_Image').src = Test[x];
(function ChangeImage() {
if(++x >= Test.length) x = 0;
document.getElementById('Test_Image').src = Test[x];
setTimeout(ChangeImage, 1000);
})();
EDIT: As Santi pointed out, my original solution only supported two images, while OP requested to loop through an array.
The difference between these two keywords in terms of scoping has already been thoroughly discussed here, but I was wondering if there is any kind of performance difference between the two, and if so, is it negligible, or at what point would it become significant?
After testing this on http://jsperf.com, I got the following results: jsperf has been down for a while; see the replacing code below.
To check this, I'll use the following performance test based on this answer, which led me to write this function:
/**
* Finds the performance for a given function
* function fn the function to be executed
* int n the amount of times to repeat
* return array [time for n iterations, average execution frequency (executions per second)]
*/
function getPerf(fn, n) {
var t0, t1;
t0 = performance.now();
for (var i = 0; i < n; i++) {
fn(i)
}
t1 = performance.now();
return [parseFloat((t1 - t0).toFixed(3)), parseFloat((repeat * 1000 / (t1 - t0)).toFixed(3))];
}
var repeat = 100000000;
var msg = '';
//-------inside a scope------------
var letperf1 = getPerf(function(i) {
if (true) {
let a = i;
}
}, repeat);
msg += '<code>let</code> inside an if() takes ' + letperf1[0] + ' ms for ' + repeat + ' iterations (' + letperf1[1] + ' per sec).<br>'
var varperf1 = getPerf(function(i) {
if (true) {
var a = i;
}
}, repeat);
msg += '<code>var</code> inside an if() takes ' + varperf1[0] + ' ms for ' + repeat + ' iterations (' + varperf1[1] + ' per sec).<br>'
//-------outside a scope-----------
var letperf2 = getPerf(function(i) {
if (true) {}
let a = i;
}, repeat);
msg += '<code>let</code> outside an if() takes ' + letperf2[0] + ' ms for ' + repeat + ' iterations (' + letperf2[1] + ' per sec).<br>'
var varperf2 = getPerf(function(i) {
if (true) {}
var a = i;
}, repeat);
msg += '<code>var</code> outside an if() takes ' + varperf1[0] + ' ms for ' + repeat + ' iterations (' + varperf1[1] + ' per sec).<br>'
document.getElementById('out').innerHTML = msg
<output id="out" style="font-family: monospace;white-space: pre-wrap;"></output>
After testing this in Chrome and Firefox, this shows that let is faster than var, but only when inside a different scope than the main scope of a function. In the main scope, var and let are roughly identical in performance. In IE11 and MS Edge, let and var are roughly equal in performance in both cases.
Press the big blue button to see for yourself in your favourite browser.
Currently let has support from only newer browsers, but older browsers are still being used relatively much, which would be a reason to generally not use it yet. If you want to use it somewhere where older browsers wouldn't function otherwise, there should be no problem with it.
Edit: revamped answer since jsperf is not working (see revision history for old version).
FYI; After Chrome v60, no further regressions have cropped up. var and let are neck and neck, with var only ever winning by less than 1%. Real world scenarios sometimes give var an advantage due to hoisting and re-use, but at that point you're comparing apples to oranges, as let is intended to allow you to avoid that behavior because the semantics are different.
Benchmark. Firefox, IE and Edge like let just fine.
Inside loops let is significantly slower see:
https://jsperf.com/let-vs-var-loop
838,602
±0.77%
61% slower
(function() {
"use strict";
var a=0;
for(let i=0;i<100;i++) {
a+=i;
}
})();
vs.
2,136,387
±1.09%
fastest
(function() {
"use strict";
var a=0;
for(var i=0;i<100;i++) {
a+=i;
}
})();
This is because when using let, for every loop iteration the variable is scoped. example:
for (let i = 0; i < 10 ; i++) {
setTimeout(function() { console.log(i); }, 100 * i);
}
yields to
0,1,2,3,4,5,6,7,8,9
using var yields to
10,10,10,10,10,10,10,10,10,10
If you want to have the same result, but using var you have to use an IIFE:
for (var i = 0; i < 10; i++) {
// capture the current state of 'i'
// by invoking a function with its current value
(function(i) {
setTimeout(function() { console.log(i); }, 100 * i);
})(i);
}
which on the other hand is significantly slower than using let.
$ node --version
v6.0.0
$ node
> timeit = (times, func) => {
let start = (new Date()).getTime();
for (let i = 0; i < times; i++) {
func();
};
return (new Date()).getTime() - start;
};
[Function]
> timeit(1000000, () => {
let sum = 0; // <-- here's LET
for (let i = 0; i < 1000; i++) {
sum += i;
if (sum > 1000000) { sum = 0; }
}
return sum;
})
12144
> timeit(1000000, () => {
var sum = 0; // <-- here's VAR
for (let i = 0; i < 1000; i++) {
sum += i;
if (sum > 1000000) { sum = 0; }
}
return sum;
})
2459
Same scope (function), same code, 5 times difference. Similar results in chrome 49.0.2623.75.
I remade dchekmarev's functions, here are my results.
Tested on Windows 10 x64 (version 1909), XAMPP, Firefox 84.0.2
Time in miliseconds:
var: let:
1622 1614
1628 1653
1872 1859
1594 1631
1614 1733
1661 1918
1606 1584
1698 1644
1648 1903
1602 1743
The results are ambiguous, but in most cases var seems a little bit faster
function varTime(times)
{
var start = (new Date()).getTime();
var sum = 0;
for (var i = 0; i < times; i++) {
for (var j = 0; j < 1000; j++) {
sum += j;
if (sum > 1000000) { sum = 0; }
}
};
console.log('var:', (new Date()).getTime() - start, ' ms');
return sum;
}
function letTime(times)
{
let start = (new Date()).getTime();
let sum = 0;
for (let i = 0; i < times; i++) {
for (let j = 0; j < 1000; j++) {
sum += j;
if (sum > 1000000) { sum = 0; }
}
};
console.log('let:', (new Date()).getTime() - start, ' ms');
return sum;
}
const times = 1000000;
const bla1 = letTime(times);
const bla2 = varTime(times);
var: Declare a variable, value initialization optional. Let is faster in outside scope.
let: Declare a local variable with block scope. Let is a little bit slow in inside loop.
Ex:
var a;
a = 1;
a = 2; //re-intilize possibe
var a = 3; //re-declare
console.log(a); //3
let b;
b = 5;
b = 6; //re-intilize possibe
// let b = 7; //re-declare not possible
console.log(b);
I went throught http://www.youtube.com/watch?v=mHtdZgou0qU speed up your javascript.
So i did this personal speed test:
var count = 50000000;
var testDummy;
// test 1
testDummy = 0;
var test1Start = new Date().getTime();
var i;
for (i=0;i<count;i++) {
testDummy++;
}
var test1End = new Date().getTime();
var test1Total = (test1End-test1Start);
// test 2
testDummy = 0;
var test2Start = new Date().getTime();
var i
for (i=count; i--;) {
testDummy++;
}
var test2End = new Date().getTime();
var test2Total = (test2End-test2Start);
debug(
"test1\n" +
"total: " + test1Total + "\n" +
"test2\n" +
"total: " + test2Total
);
I get not significant results, like sometimes they are even and sometimes not.
My question is, if i use for loop like this: "for(i=count;i--;)" is it really faster ?
Am i doing something wrong in my tests.
Thanks for your help!
(I'd write this as a comment, but it'd be too long.)
First: Worrying about the efficiency of a for loop is almost always a waste of (your own) time. What's inside of the loop usually has much more impact on performance than the details of how the loop is specified.
Second: What browser(s) did you test with? Different browsers will show different performance profiles; even different versions of the same browser will differ.
Third: It's not out of the question that the JavaScript engine optimized your loops out of the picture. A JavaScript compiler could simply look at the loop and decide to set testDummy to 50000000 and be done with it.
Fourth: If you really want to split hairs on performance, I'd try for(i=count; --i != 0;) as well as for(i=count;i--;). The former may save a machine instruction or two, because executing the subtraction (in the predecrement step) may automatically set a hardware flag indicating that the result was 0. That flag is potentially wasted when you're using the postdecrement operator, because it wouldn't be examined until the start of the next iteration. (The chances that you'd be able to notice the difference are slim to none.)
Well...
for( i=0 ; i < len ; i++ )
is practically the same as
for( i = len ; i-- ; )
Lets describe it:
case 1:
let i be 0
boolean expression
let i be i + 1
case 2:
let i be len
let i be i - 1
cast i to boolean (type coersion) and interpret it.
The difference should be minute and depends entirely on how efficient type coersion is compared to a normal boolean expression.
Incidentally, test this:]
var i = count;
while( i-- ) {}
There's nothing wrong with your tests.
The blocks that you are testing are very-near identical, meaning the difference in execution speeds are going to be trivial. In both examples, a variable (i) is set to a fixed value and looped until it reaches a fixed value (count). The only thing that differs is i++ and i--, which in terms of speed, I think are practically the same.
The thing you have to be careful of (not do) is calculate the "loop until" value inside the loop definition.
I have made some tests too, here are the results.
In many articles, books authors propose that "optimized" loops are faster.
It seems that modern browsers have some optimizations for "normal" loops.
Firefox 13.0.1
Normal Loop: 0.887
Opt1: 1.025
Opt2: 1.098
Opt3: 1.399
Chrome 19.0.1
Normal Loop: 3.349
Opt1: 3.12
Opt2: 3.109
Opt3: 3.095
IE8
Over 12sec...
Repeatedly crashed during tests.
<script type="text/javascript">
function p(p) { console.log(p); }
// function p(p) { document.write(p); }
var testFn = function(num, niz, fn) {
var start = new Date().getTime();
fn(num, niz);
var result = (new Date().getTime() - start) / 1000;
return result;
}
function normalLoop(num, niz) {
for (var i = 0; i < niz.length; i++) {
niz[i] = 'a' + i;
}
}
function opt1(num, niz) {
var len = niz.length;
for (var i = 0; i < len; i++) {
niz[i] = 'a' + i;
}
}
function opt2(num, niz) {
for (var i = niz.length; i--;) {
niz[i] = 'a' + i;
}
}
function opt3(num, niz) {
while(i--) {
niz[i] = 'a' + i;
}
}
var niz = [];
var num = 10000000;
for (var i = 0; i < num; i++) { niz.push(i); };
p('Normal Loop: ' + testFn(num, niz, normalLoop));
p('Opt1: ' + testFn(num, niz, opt1));
p('Opt2: ' + testFn(num, niz, opt2));
p('Opt3: ' + testFn(num, niz, opt3));
</script>