Count down and change variable as it happens [duplicate] - javascript

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
}

Related

Calculate elapsed time in Javascript

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' );

Javascript, setting timeout between events in one function

lets say I have a function in a loop that will display two different kinds of text interchangeably over and over.
Now what I want to achive is for the different text to be displayed with a delay, let's say 1 second. So it would print 1st text and after 1 second 2nd text and so on untill the loop is over. I was trying to use setTimeout and setInterval but I cannot get it to work.
var a = "hey ";
var b = "ho ";
function test(a,b){
document.getElementById('id').innerHTML += a;
document.getElementById('id').innerHTML += b;
}
for(var i = 0; i < 10; i++){
setInterval(test(a,b), 1000);
}
<div id="id">
</div>
You need to use setTimeout to introduce delay and not setInterval.
Timeout should be in incremental order so multiply it with i
test(a,b) should be in callback of the function so that setTimeout can execute it based on the delay. If you will directly write test(a,b) then it will get executed right then and there without any delay.
var a = "hey ";
var b = "ho ";
function test(a,b){
document.getElementById('id').innerHTML += a;
setTimeout(function(){
document.getElementById('id').innerHTML += b;
}, 500)
}
for(var i = 0; i < 10; i++){
setTimeout(function(){
test(a,b);
}, i*1000);
}
<div id="id">
</div>
UPDATE
Delay between document.getElementById('id')
You could use a setInterval and keep track of how many were done with a variable :
var count = 0; //Variable to keep track of the number of setInterval called
var text = ['text1','text2'];
var interval = setInterval(() => {
if(count == 10) clearInterval(interval); //Stop the setInterval when you reach the 10th time
document.getElementById('test').innerHTML = count % 2 == 0 ? text[0] : text[1];
count++; //Increment your var
},1000);
<div id="test"></div>
You can use an "asynchonous" loop for this, i.e. a function that calls itself after a time out. Then use the modulo operator to decide whether to show a or b:
var a = "hey ";
var b = "ho ";
function test(c){
document.getElementById('id').innerHTML += c;
}
(function loop(i){
if (i >= 10) return; // All done
test(i%2 ? b : a); // choose which one to show
setTimeout(loop.bind(null, i+1), 1000); // Repeat with delay and incremented i.
})(0); // Start the loop immediately with i=0
<div id="id">
</div>
function loop(i, limit) {
if (i < limit) {
console.log('Text 1');
setTimeout(function() {
console.log('Text 2');
setTimeout(function() {
loop(++i,limit);
},1000);
},1000);
}
}
loop(0,3);
You need to change your code around a bit to introduce a delay between each.
The code below:
stores the possible values in the array
has a method which will display the ith element from the values
has a run method used to start the loop, and also recalled with a delay (1second) having incremented a counter
var values = ["hey","ho"];
var index = 0;
function display(i){
document.getElementById('id').innerHTML = values[i];
}
function run(){
display(index%values.length)
if(++index<10){
setTimeout(run,1000);
}
}
run();
<div id="id">
</div>
If you want the timeout between 'hey' and 'ho' also, you shouldn't be keeping both of them inside test, instead keep only one and change the param value.
var a = "hey ";
var b = "ho ";
function test(a){
document.getElementById('id').innerHTML += a;
}
for(var i = 0; i < 10; i++){
(function(i) {
setTimeout(function(){
test(i % 2 === 0 ? a : b);
}, i*1000);
}(i))
}
<div id="id">
</div>

JavaScript - Console-like output for API calls

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.

How define a couple of setIntervals and clear them with delay

I need to randomly change characters of a text and after some delay fix them.
There is my code:
<h1 id="text" style="margin-top:100px;">SOME TEXT</h1>
<script>
var text = document.getElementById("text").innerHTML.split("");
var myArr = text;
for (i = 0; i < myArr.length; ++i) {
var handle = setInterval(function () { xyz(i) }, 100);
setTimeout(function (handle) {
myArr[i] = text[i];
clearInterval(handle);
}, (i) * 1000);
}
function xyz(index) {
myArr[index] = String.fromCharCode(Math.random() * 26 + 65);
document.getElementById("text").innerHTML = myArr;
}
</script>
It seems i have no a good understanding of how setInterval work! :(
EDIT:
With my code only text[text.length+1] character has change that mean passed parameter to xyx() function is last value of loop counter variable (after loop over). Now my question is how trigger setInterval() function with i = 0 ,1 ... , text.length.
Can someone guide me?
basicly setInterval execute a function with a iteration in time. and setInterval gives you a promise to cancel it any time you want.
var myPromise = setInterval(function(){
//some code here
},delayMiliseconds);
to cancel this code
clearInterval(myPromise);
Related to this question problem was wrong way to passing arguments to setInterval().the callback function i passed to setInterval() maintains a reference to "i" rather than the snapshot value of "i" as it existed during each particular iteration...
<h1 id="text" style="margin-top:100px;">SOME TEXT</h1>
<script>
var text = document.getElementById("text").innerHTML.split("");
var myArr = document.getElementById("text").innerHTML.split("");
for (i = 0; i < text.length; i++) {
var handle = setInterval(function (k) { xyz(k) }, 100,i);
setTimeout(function (handle, i) {
console.log(i);
console.log(text[i]);
myArr[i] = text[i];
clearInterval(handle);
}, (i) * 1000,handle,i);
}
function xyz(index) {
myArr[index] = String.fromCharCode(Math.random() * 26 + 65);
document.getElementById("text").innerHTML = myArr.toString();
}
</script>

Image not changing

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.

Categories

Resources