Constantly check if date is in the past - javascript

I want to check if selected date is in the past in 'for loop'. But if I use 'for loop' it stops other code from running. How can I constantly check if date is in the past and not stopping other code from running?
for (var now = new Date();;) {
if (selectedDate < now) {
// some code
}
}
console.log('1') // code that's not running.

JavaScript is fully synchronous and single-threaded. Therefore, your code is getting "locked-up" or stuck at the for loop you have referenced.
You need to use setInterval. For example:
// For demonstration purposes.
var selectedDate = new Date();
// The code inside of this function will run every 1 second (or 1,000 milliseconds)
setInterval(function () {
var now = new Date();
if (selectedDate < now) {
console.log("Selected date is in the past!");
}
}, 1000);
console.log('1') // This code runs now because JavaScript is not caught executing the for loop.

Lot of solutions for resolve this problem. You can use an Observable if ou use RXJS. Else you can use a simple interval with an arrow function or a simple funtion and define repeat time interval in millisecond :
setInterval(repeatFunc,intervalInMillisecond);

Related

Javascript loop clicker

I'm trying to make a javascript script running from the urlbar which for each row on a specific page clicks a button (allowing me to change a certain value), then edit that value, then click that button again to confirm. I'm running into a lot of trouble with simultaneity, as it seems to wait to do the first click 5000 ms even tho it's not being told to pause. didn't do the same when i tested the structure replacing things in between pauses with rando alerts
The reason for the pauses is bc there's a short loading animation during which I can't execute code. Anything glaringly wrong in this as-is? I know there's funky stuff w/ closure, but I thought by busywaiting i could get past it but its not.
function pause(milliseconds) {
var dt = new Date();
while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}
var q=document.getElementById("MainContent_gvProducts").children[0];
var l=q.children.length;
for(i=1;i<l;i++){
q.children[i].children[0].children[0].click();
pause(5000);
var x=q.children[i].children[7].children[0].value;
pause(1);
x=math.round(x);
pause(5000);
q.children[i].children[0].children[0].click();
pause(5000);
}
Your pause function seems very hacky.
You should use setTimeout() instead, or something similar.
If you can afford to use the latest JS tech, I'd recommand creating a promise with a timeout and using async/await, with something like this :
async function pause(t = 1000) {
return new Promise(resolve => {
setTimeout(() => {
resolve(true)
}, t)
})
}
for(i=1;i<l;i++){
q.children[i].children[0].children[0].click();
await pause(1000)
var x=q.children[i].children[7].children[0].value;
pause(1);
x=math.round(x);
await pause(5000);
q.children[i].children[0].children[0].click();
await pause(5000);
}
Note : your for loop must be placed in an async function.

Sending a JavaScript interpreter back to the top of your code

Say I have 20 rows of JS code and I want the interpreter to execute only half of the code (<11 rows), then stop, without functions and returns, or without commenting the rest of the code (I already tried a return, see in advance).
A location.reload(true); in row 10 is a close solution but I'm looking for a client side stop.
My question
Is there like a stop command (or functionality) in JavaScript, that asks the interpreter to stop and behave as if no code ran so far?
Why I ask
The background for this question is a problem I have calling a function in more than one keydown event.
Given the keydown event is triggered only once, I consider sending the interpreter back to the start after the keydown event was triggered disposably, and without refreshing the page (Sorry if it seems absurd, I'm new to JS and failed finding the source of the bug).
Of course, the above question is different than the question "why does the keydown event triggered only once", which I already asked here - here's a link for context.
Preventing an XY problem
On one hand, I want to make sure there is no XY problem. On the other hand, I am not allowed to copywrite the previous question to this session hence linked to it above.
Either way, I would be glad to know if what I just described (client side stop of a JS interpreter) is even possible in the current release of the language.
Note: I decided to carefully rewrite the question after some comments earlier today (there were no answers) and did my best ensuring the question is informative and communal.
There is no stop command, but I experienced the need of it before when there was a long-running client-side operation.
The solution:
1) Divide the problem into small packets
2) Make sure you are able to make your function work only for activeMilliseconds milliseconds:
function doStuff(packets, currentIndex, activeMilliseconds) {
var start = new Date(); //Start of chunk
while((currentIndex < packets.length) && (new Date() - start < activeMilliseconds)) {
//Do something with packets[currentIndex]
currentIndex++;
}
return currentIndex;
}
3) Now that we are able to work for activeMilliseconds milliseconds, we need to use this asynchronously:
//Define packets
var currentIndex = 0;
var intervalID = setTimeout(function() {
If(currentIndex = doStuff(packets, currentIndex, activeMilliseconds) >= packets.length) clearInterval(intervalID);
}, totalMilliseconds);
Node: totalMilliseconds > activeMilliseconds should be true. For example, if totalMilliseconds is 250, and activeMilliseconds is 200, then in each 250 milliseconds a chunk will run for 200 milliseconds, leaving the browser to do its stuff for 50 milliseconds every 250 milliseconds even if there is a lot of work to do.
4) Make sure a job stops a previous similar job:
function doJob(packets, intervalID, activeMilliseconds, totalMilliseconds) {
clearInterval(intervalID);
//Define packets
var currentIndex = 0;
var intervalID = setTimeout(function() {
If(currentIndex = doStuff(packets, currentIndex, activeMilliseconds) >= packets.length) clearInterval(intervalID);
return intervalID;
}, totalMilliseconds);
}
If you use this idea for your key event, then it will stop the previous keyboard, your maximum wait time to do so will be activeMilliseconds, which is an acceptable compromise in my opinion.
That said, this methodology should be only used in the case when you have no other option. You need to know that Javascript has a single thread, so even if you trigger a function execution while a previous instance of the event is still running, your new event will sequentially be executed when the other event is finished.

Why is JavaScript blocking the ui update (via jquery) here?

In this code, why does the css change not complete until the while loop finishes? I know a loop hangs the browser but I would have thought the css change would be synchronous and therefore finish before the while loop even starts.
Bonus Question: Is there any way for me to get that css change to complete before moving to the while loop without giving up control of the javascript thread?
function run() {
var then = +new Date()
, now
;
$('#mydiv').css('display','block');
now = + new Date();
while (now - then < 5000) {
now = +new Date();
}
}
fiddle: http://jsfiddle.net/ezVZT/2/
Browsers don't always update the page immediately. They'll often wait with updates rendered but not painted while scripts execute and batch all the repainting together.
In your code you're applying a change to the styling, but then executing a 5 second loop which will block everything. The CSS change just has to wait.
If you need to wait five seconds before doing something use a setTimeout() call, or since you're using jQuery, look at .delay().
Would something like $elem.addClass('xyz') solve your problem? you can then assign the display: block to your class in css. Maybe that would be faster?
Try the following code. It might work.
function run() {
var then = +new Date()
, now
;
$('#mydiv').css('display','block');
$("#mydiv", window.parent.document).load($("mydiv").html());
now = + new Date();
while (now - then < 5000) {
now = +new Date();
}
}
function reset() {
$('#mydiv').css('display','none');
}

How many timers in a window? [duplicate]

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

Timeout a function in JavaScript/jQuery

I've got the following problem:
I'm using Google Maps on my site. I've attached the following eventListener to the map itself:
google.maps.event.addListener(map, 'bounds_changed', scheduleDelayedCallback);
The event bounds_changed is called every time someone drags the map. My Problem is, that it is called several times during the drag process. Now I need to find a way to call the callback function only, if it wasn't called during the last, let's say, 750 milliseconds.
I did this using these two functions:
function fireIfLastEvent() {
var now = new Date().getTime();
if (lastEvent.getTime() + 750 <= now) {
this_function_needs_to_be_delayed();
} else {
$("#main").html('Lade...');
}
}
function scheduleDelayedCallback() {
lastEvent = new Date();
setTimeout(fireIfLastEvent, 750);
}
This method works great in Chrome and Opera. In IE it works sometimes, in Firefox it never works (it calls the functions even if the 750 milliseconds haven passed).
Is there any rock-solid way to timeout a function call?
Thanks.
You shouldn't need a timeout here.
function scheduleDelayedCallback() {
var now = new Date();
if (now.getTime() - lastEvent.getTime() >= 750) {
// minimum time has passed, go ahead and update or whatever
$("#main").html('Lade...');
// reset your reference time
lastEvent = now;
}
else {
this_function_needs_to_be_delayed(); // don't know what this is.
}
}
Your explanation of what you want to happen isn't the clearest so let me know if the flow is wrong.

Categories

Resources