Show message while javascript is running - javascript

I know that most probably such question has been requested several times but I have a need to show a popup or message or whatelse when a javascript function is triggered and hide it at the end.
See this simple js fiddle
That's the HTML code:
<div id='message'>Default message</div>
<input type='button' onclick='Run();' value='start'>
the div 'message' has to contain a simple text like "running" or "please wait" or ...
That's the JS function that took (delay) 3 seconds:
function Run() {
var delay = 3000; //-- 3 seconds
$( '#message' ).text('Please wait ' + delay + ' seconds...');
var start = new Date().getTime();
while (true) {
current = new Date().getTime();
if ( (start + delay) < current) {
break;
}
}
$( '#message' ).text('Done');
}
The expected behaviour is that the '#message' div contains "Please wait 3 seconds..." before to enter in the loop and "Done" string only at the end.
But that's not.
Can anyone explain me (most probably "again") why or suggest a link where to find an answer?

The JS event loop is too busy running while (true) {} to handle a DOM repaint.
Use setInterval, setTimeout, or requestAnimationFrame to trigger the next test of the time instead of a loop.
function Run() {
var delay = 3000; //-- 3 seconds
$( '#message' ).text('Please wait ' + delay + ' seconds...');
var start = new Date().getTime();
setTimeout(whenDelayIsOver, 50);
function whenDelayIsOver() {
if ( (start + delay) < current) {
$( '#message' ).text('Done');
} else {
setTimeout(whenDelayIsOver, 50);
}
}
}
… or just use setTimeout in the first place.
function Run() {
var delay = 3000; //-- 3 seconds
$( '#message' ).text('Please wait ' + delay + ' seconds...');
setTimeout(whenDelayIsOver, delay);
function whenDelayIsOver() {
$( '#message' ).text('Done');
}
}

Try this http://jsfiddle.net/aamir/23ZFY/11/
function Run() {
var secs = 3;
$('#message').text('Please wait '+ secs +' seconds...');
var timer = setInterval(function () {
if (secs == 1) {
clearTimeout(timer);
$('#message').text('Done');
return;
}
secs--;
$('#message').text('Please wait ' + secs + ' seconds...');
}, 1000);
}

The browser's display is only updated when the function completely finishes running.
You can run the second lot of code asynchronously by using setTimeout.
function Run() {
$('#message').text('Please wait 3 seconds...');
setTimeout(
function () {
var start = new Date().getTime();
while (true) {
current = new Date().getTime();
if ((start + 3000) < current) {
break;
}
}
$('#message').text('Done');
},0);
}

You have a very tight loop (while(true)...) which doesn't allow the UI to update at all. What you can do instead is this:
function Run() {
var delay = 3000; //-- 3 seconds
$('#message').text('Please wait ' + (delay/1000) + ' seconds...');
setTimeout(function () {
$('#message').text('Done');
}, delay);
}
Basically, set the "wait message" initially and use the setTimeout function to update the message again after 3 seconds.
Updated fiddle.

Related

Sleep , freeze, end?

could you please help me how to fix this? I want to send just one command, but to be as accurate as possible (on milliseconds).
This is the part I need to fix:
document.getElementById("arrTime").onclick = function () {
clearInterval(attInterval);
let time = document.getElementsByClassName("relative_time")[0].textContent.slice(-8);
input = prompt("Set Arrival Time", time);
inputMs = parseInt(prompt("Set the milliseconds", "500"));
delay = parseInt(delayTime) + parseInt(inputMs);
let arrivalTime;
arrInterval = setInterval(function () {
arrivalTime = document.getElementsByClassName("relative_time")[0].textContent;
if (arrivalTime.slice(-8) >= input) {
setTimeout(function () { document.getElementById("troop_confirm_submit").click(); }, delay);
}
}, 5);
document.getElementById("showArrTime").innerHTML = input + ":" + inputMs.toString().padStart(3, "0");
document.getElementById("showSendTime").innerHTML = "";
};
Now, there is an "if statement" to perform action at arrivalTime.slice(-8) >= input (so for example 19:24:30), but it is sending requests every 5ms. So over that one second time, it sends 200 requests to the server.
I don´t want to change those 5ms, as I need to have it as accurate as possible, but I want to break the script, freeze it or sleep it for 1 second once the command is performed. So something like: setTimeout(function () { document.getElementById("troop_confirm_submit").click(); Sleep 1 second }, delay);
Anyone who can help, please?
I'd advise to break up the functions as to manage the interval a little easier
document.getElementById("arrTime").onclick = function() {
clearInterval(attInterval);
let time = document.getElementsByClassName("relative_time")[0].textContent.slice(-8);
input = prompt("Set Arrival Time", time);
inputMs = parseInt(prompt("Set the milliseconds", "500"));
delay = parseInt(delayTime) + parseInt(inputMs);
startInterval(input, delay)
document.getElementById("showArrTime").innerHTML = input + ":" + inputMs.toString().padStart(3, "0");
document.getElementById("showSendTime").innerHTML = "";
};
function startInterval(input, delay) {
arrInterval = setInterval(function() {
let arrivalTime = document.querySelector(".relative_time").innerText;
if (+arrivalTime.slice(-8) >= +input) {
clearInterval(arrInterval); // pause the interval
setTimeout(() => {
startInterval(input, delay)
}, 1000 * 60); // restart the interval in 1 minute
setTimeout(() => {
document.querySelector("#troop_confirm_submit").click();
}, delay);
}
}, 5);
}

javascript set interval time every 3 sec for first 6 seconds, then 5 seconds continuously till i receive the answer

I want to ping a server for response every 3 seconds for the first 6 seconds, after that I want to increase the interval time to 5 seconds till i get the response. I did the first part, I'm trying to solve the next 5 seconds ping
var firstPing = 3000,
pingStop = 6000,
pingForever = 5000;
var ping = setInterval(function() { execute() }, firstPing);
setTimeout(function() {clearInterval(ping)}, pingStop);
setInterval(function() {execute()}, pingForever);
function execute() {
console.log('hello: ' + new Date().getSeconds());
// After successful response, clearInterval();
}
Might it be simpler to just call execute() every 1 second and only have execute do something when an incrementing counter variable is a certain value?
var ping = setInterval(function() { execute() }, 1000);
let v = 0;
function execute() {
v++;
if(v==3 || v==6 || (v>6 && v%5 == 1))
console.log('hello: ' + new Date().getSeconds());
// After successful response, clearInterval();
`
Here is something that manages the transition of the ping from 3 to 5 secs.
const firstPing = 3000,
pingStop = 6000,
pingForever = 5000;
let currentPing = 0;
let ping = setInterval(function() { execute() }, firstPing);
function execute() {
console.log('hello: ' + new Date().getSeconds());
// After successful response, clearInterval();
if(++currentPing >= 2 ) {
clearInterval(ping);
ping = setInterval(() => execute(), pingForever);
}
}
You can use count variable, you have firstPing of 3sec. Instead of clearing the interval you can update the firstPing with pingForever.
var firstPing = 3000,
pingStop = 6000,
pingForever = 5000;
let count = 0;
var ping = setInterval(() => {
execute();
firstPing = (count === 2) ? pingForever : firstPing;
count++;
console.log(count, firstPing);
}, firstPing);
function execute() {
// console.log('hello: ' + new Date().getSeconds());
}
I would just use setTimeout for simplicity.
var found = null;
function tryRequest() {
if (found) return;
// send request
// in successful response, set 'found' to 'true'
setTimeout(tryRequest, found == null ? 3000 : 5000);
found = false;
}
setTimeout(tryRequest, 3000);

How to terminate endless while loop via setTimeout in Javascript

I have a piece of code with while loop which I would like to stop by setTimeout(). But it seems like a endless loop, which never triggers setTimeout(). If I remove while loop, timeout triggers correctly. What is wrong please?
$(document).ready(function()
{
var i = 0, s = false;
setTimeout( function()
{
s = true;
console.log( "Timeuot!!!" );
console.log( "s value is " + s );
}, 1000 );
while( s === false )
{
console.log( "this is while and s is " + s );
i++;
}
console.log( "iterations: " + i );
});
JavaScript runs a single event loop. It won't stop in the middle of a function to see if there are any events (such as clicks or timeouts) that would trigger a different function.
In short: It won't run the timed function until the while loop has finished.
To do this sort of thing, you'd normally have an event driven iterator.
var i = 0,
s = false;
setTimeout(function() {
s = true;
console.log("Timeuot!!!");
console.log("s value is " + s);
}, 1000);
next();
function next() {
if (s) {
return done();
}
console.log({
s, i
});
i++;
setTimeout(next, 0);
}
function done() {
console.log("iterations: " + i);
}
As already mentioned the while loop blocks the one and only thread. To let your example do the thing you want, replace the while loop with setInterval(function) like this:
$(document).ready(function()
{
var i = 0, s = false;
setTimeout( function()
{
s = true;
console.log( "Timeout!!!" );
console.log( "s value is " + s );
}, 1000 );
var interval = setInterval(function() {
console.log( "this is while and s is " + s );
i++;
if (s) {
clearInterval(interval);
console.log("i is " + i)
}
}, 100);
});
setTimeout is never called do the the fact that the while never ends and so the even dispatcher is not going to trigger the setTimeout.

Countdown and bootstrap progress bar "bump"

I'm working on a little "web app" for a quiz.
Each slide has got a certain amount of time to be answered (or 0 to infinite time).
I find JS here to do the countdown:
function Countdown(options) {
var timer,
instance = this,
seconds = options.seconds || 10,
updateStatus = options.onUpdateStatus || function () {},
counterEnd = options.onCounterEnd || function () {};
function decrementCounter() {
updateStatus(seconds);
if (seconds === 0) {
counterEnd();
instance.stop();
}
seconds--;
}
this.start = function () {
clearInterval(timer);
timer = 0;
seconds = options.seconds;
timer = setInterval(decrementCounter, 1000);
};
this.stop = function () {
clearInterval(timer);
};
}
var myCounter = new Countdown({
seconds: timetogo, // number of seconds to count down
onUpdateStatus: function (sec) {
elapsed = timetogo - sec;
$('.progress-bar').width(((elapsed / timetogo) * 100) + "%");
}, // callback for each second
onCounterEnd: function () {
//alert('counter ended!');
} // final action
});
myCounter.start();
I made a jsfiddle here :
https://jsfiddle.net/mitchum/kz2400cc/2/
But i am having trouble when you go to the next slide, the progress bar "bump".
after looking into "live source panel from chrome" I saw it's like the first "counter" is not stopped and still runs.
Do you have any tips or hint to help me to solve my bug ?
Thanks
You must pay attention to the scope of the variables. I change the "var myCounter" under document ready in "var myCounterFirst". Check the updated JSFiddle.
var timetogoFirst = $('.current').attr("data-time");
var myCounterFirst = new Countdown({
seconds: timetogoFirst, // number of seconds to count down
onUpdateStatus: function (sec) {
elapsed = timetogoFirst - sec;
$('.progress-bar').width(((elapsed / timetogoFirst) * 100) + "%");
}, // callback for each second
onCounterEnd: function () {
alert('counter ended!');
} // final action
});
myCounterFirst.start();

How to run jquery function after the animation has completed?

so i'm new to javascript and jquery. Need some help on how to run the 2nd function after the 1st one has completed?
The first function is a progress bar and the second one is a form that i want to fade in after the progressbar animation completed.
The script:
$(function() {
var msecsPerUpdate = 1000 / 60; // # of milliseconds between updates, this gives 60fps
var progress = $('progress');
var duration = 1; // secs to animate for
var interval = progress.attr('max') / (duration * 1000 / msecsPerUpdate);
var animator = function() {
progress.val(progress.val() + interval);
if (progress.val() + interval < progress.attr('max')) {
setTimeout(animator, msecsPerUpdate);
} else {
progress.val(progress.attr('max'));
}
}
$('a#forgot').click(animator);
});
$(function(e) {
e.preventDefault();
$('generator#forgot').css('bottom', '5px');
$(this).fadeOut('medium', function() {
$('a#back').fadeIn();
});
});
Thanks in advance!
I'd add a callback function to your animator function to make it look like this:
var animator = function(callback) {
progress.val(progress.val() + interval);
if (progress.val() + interval < progress.attr('max')) {
setTimeout(animator, msecsPerUpdate);
} else {
progress.val(progress.attr('max'));
callback();
}
}
Then you can call it like this:
$('a#forgot').click(function() {
animator(function() {
console.log('this runs after your animation has completed');
});
});
Note: this is a simplified code-snippet without params or error handling, which you might wanna add.

Categories