Extend the timeout duration of a setTimeout timer - javascript

Hi Everyone I know it is basic and silly to ask but this question is eating me up .
If I have a below following code .
var timerVal = 900000
function myFunction() {
setTimeout(function(){ alert("Hello"); }, timerVal);
}
myFunction()
As per the above code an alert will come at 15 mins . But after ten minutes I thought to extend it for more 5 mins by changing the value of timerVal to 1200000. Now would the alert will come after another 10 mins . i.e. total 20 mins after the alert will come or it will come after 15 mins of the completion .
Suppose the code is like this :
var timerVal = 900000
function myFunction() {
setTimeout(function(){ alert("Hello"); }, timerVal);
}
function change(){
setTimeout(function(){
timerVal = 1200000;
},60000);
}
myFunction();
change();
Can Anyone give let me know what will be the result and brief description why ?

The result will be that the timer will be executed at the 900000 millisecond mark, although you have tried to change it to 1200000 millisecond by changing the value of the timerVal variable.
This is because in JavaScript it is pass by value and since you have passed 900000 initially, the timer is already queued at 900000 and hence cannot be altered by changing the value of the timerVal variable again.
So this code, is simply making the timerVal point to the new number 1200000 not really changing the timeout set earlier:
function change(){
setTimeout(function(){
timerVal = 1200000; //timerVal reference is pointing to a new number
}, 60000);
}
To really change the timer behavior you need to clear the timeout using the id returned by the setTimeout call and create another one with the new timeout value.
let timerVal = 9000;
function myFunction() {
return setTimeout(function(){ alert("Hello"); }, timerVal); //returning the id
}
function change(id, newVal){
clearTimeout(id); //clearing the previous timer using the id
setTimeout(function(){ alert("Hello"); }, newVal);
}
let id = myFunction();
change(id, 5000);

Well, in general to be able to "extend" a timer, you'll need to cancel it (using clearTimeout), and re-create it. For this you'll need to keep track of how long has elapsed since it originally started and calculate a new time.
The code below demonstrates a function extendableTimeout which you can use like the normal setTimeout, except it returns an object with an extend function you can use for your purpose.
The demo has 2 button, the first starts an action delayed for 5s. Clicking the extend button extends the timeout by another 5 seconds. You can compare clicking the extend or not to see the timings.
function extendableTimeout(fn, time){
var id = setTimeout(fn, time);
var timeStart = new Date();
return {
timerId: id,
extend: function(time){
clearTimeout(id);
var elapsed = new Date() - timeStart;
var newTime = time - elapsed;
setTimeout(fn,newTime);
}
}
}
var myTimer;
$('#start').on("click", function(){
console.log("Started at " + new Date());
myTimer = extendableTimeout(() => console.log("Finished at " + new Date()), 5000);
})
$("#extend").on("click", function(){
myTimer.extend(10000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="start">Start</button>
<button id="extend"> + 5s </button>

AFAIU, you cannot extend the time of a setTimeout. What you can do is stopping it from executing, and create another setTimeout with the new value. Like this:
var timer = setTimeout(()=>console.log("first"), 2000);
clearTimeout(timer);
var timer = setTimeout(()=>console.log("second"), 2000);
You cannot extend it because the timer is created with the value the variable had at the time of creation event. It's not a reference that can be evaluated from time to time. It's a fixed value that is evaluated only on creation time.

Related

setTimeout doesn't work inside setInterval

I'm building a chrome addon in manifest v2. I have an interval that runs every minute. Inside it, I have a function that supposed to reload the page will reload every 3 minutes if a boolean is false. If it is true, the timer of the 3 minutes need to reset itself.
For some reason, when I'm setting the timer and logging it, it is stuck at '1'. It will move only when I will consantly set it again - which by theory should reset it but nope - it just continues.
When I call for clearTimeout, nothing happens - the timer stays the same. Even if I try to equel the timer variable into a null, it's still continues regularly.
This is the code, hope that you could help me figure this out:
var timerLoop = [].
var audioPlayed = false;
var timer = null;
function clearTimerLoop(){
for ( var i = 0; i < timerLoop.length; ++i ){
clearTimeout( timerLoop[i] );
timerLoop[i] = null; //Tried here to make it a null, no success
}
timerLoop = []; //Tried here to remove everything from the array, no success
console.log("Timer cleared");
}
function startTimer(){
timer = window.setTimeout(refreshPage, 180000); /* reload every 3 minutes */
timerLoop.push(timer);
console.log("Timer created");
}
loopInterval = setInterval(function(){loopChecker();}, 60000);
function loopChecker(){
if(audioPlayed){
clearTimerLoop()
timer = null;
audioPlayed = false;
}
if(!audioPlayed && timer == null){
startTimer();
console.log("Refresh timer running (" + timerLoop[0] + ")");
}
console.log(timer);
}
Thanks in advance.
As you can see I am resetting the timer as much as I can but nothing happens. In addition, the timer is stuck on 1 unless I set it again in every timer loopChecker() runs, and again - this should reset it but it continues.
I thought maybe every run sets a new timer so I created an array that pushes the timer each time it's created and then when I want to clear, every timer is cleared. Didn't help.
Instead of doing all of that, you can just do something like this:
timer = null
if (boolean == false) {
timer = setInterval(() => {
window.location.reload();
}, 180000)
...
}
else {
clearInterval(timer);
timer = null; // stops page reloading every 3 min by deleting setInterval and its callback
...
}

How to make the page go back to the beginning after a certain time? [duplicate]

This question already has answers here:
How to detect idle time in JavaScript
(37 answers)
Closed 10 months ago.
I'm creating a webpage and I decided to try to get you back to the start automatically if it takes a certain amount of time without clicking the screen. I tried to do so but when I enter the page no matter how much it touches the screen the time does not reset and the alert appears anyway. The webpage is also loading and does not load all the content. Here is the code I currently have:
var startTime = new Date();
document.addEventListener('DOMContentLoaded', function(){
var seconds = 1;
while (seconds < 5) {
endTime = new Date();
var timeDiff = endTime - startTime; //in ms
// strip the ms
timeDiff /= 1000;
// get seconds
var seconds = Math.round(timeDiff);
console.log(seconds + " seconds");
setTimeout(() => {}, 1000); // Like time.sleep
}
alert("Touch the screen!")
})
document.addEventListener("click", function() {
console.log("Hello")
startTime = new Date()
});
Thank you!
This will check every 5 seconds if any activity has occurred, if not then trigger your page update.
var timestamp = Date.now();
var checkTime = null;
document.addEventListener('DOMContentLoaded', function(){
checkTime = setInterval(doTimeout, 5000);
});
document.addEventListener("click", function() {
console.log("Hello")
timestamp = Date.now();
});
function doTimeout(){
if (Date.now() - timestamp >= 5000){
console.log("change page");
}
}
The setTimeout function is an async function, so is not block the main thread.
You should use
let startTime=new Date();
setInterval(function() {
let currentTime=new Date();
let timeDiff=(currentTime-startTime)/1000;
if(timeDiff>5) {/*code to scroll up the page*/}
},200) //it checks every 200 millisecodns the time
document.addEventListener("click", function() {
console.log("Hello")
startTime = new Date()
});
The "DOMContentLoaded" is fired once the HTML document is loaded, this often means that it is before css and images are loaded to the page, which could explain why your page isn't fully loading. I don't see any logic which is resetting the timer once the page is clicked, you should have an on click event listener which will reset the timer, and move the timer variable outside of a level of scope so that both event listeners can use it.
I think you have a misconception about how setTimeout works.
With setTimeout you can register a function that will be called after the indicated number of ms has passed.
The function you give it is a noop, so I'm guessing you imagine setTimeout to have a side effect. In this situation particularly, I'm guessing you are expecting setTimeout to halt the execution of the loop, but that isn't the case. If you are expecting it to work like a time.sleep function, thats not how it works, since after registering the callback, it simply moves on.
So the page isn't fully loading, because it has to continously run this while loop, and can't do anything else until it's done with that.
To get something more similar to time.sleep you can use async/await.
function sleep(ms){
return new Promise(resolve => setTimeout(resolve, ms));
}
document.addEventListener('DOMContentLoaded', async function(){
var seconds = 1;
while (seconds < 5) {
endTime = new Date();
var timeDiff = endTime - startTime; //in ms
// strip the ms
timeDiff /= 1000;
var seconds = Math.round(timeDiff);
console.log(seconds + " seconds");
await sleep(1000)
}
alert("Touch the screen!")
})
In the above I defined a helper function, sleep, which creates a Promise, that simply resolves after the indicated amount of ms has passed.
To use this, the function using it has to be marked as async. That's why you can see the async keyword right before the function keyword in the addEventListener call.
Once that requirement is fulfilled, you can use the sleep function by adding the await keyword in front of it.
call setTimeout once then call clearTimeout if there are touch or click event
document.addEventListener('DOMContentLoaded', function() {
var timeout = setTimeout(function() {
console.log('page will go back!');
}, 3000);
["click", "touchstart"].forEach(function(event) {
document.addEventListener(event, function() {
clearTimeout(timeout)
console.log('will not go back')
});
})
});

How do i make a javascript fuction repeat every few seconds? [duplicate]

I want repeat this code every 4 seconds, how i can do it with javascript or jquery easly ? Thanks. :)
$.get("request2.php", function(vystup){
if (vystup !== ""){
$("#prompt").html(vystup);
$("#prompt").animate({"top": "+=25px"}, 500).delay(2000).animate({"top": "-=25px"}, 500).delay(500).html("");
}
});
Use setInterval function
setInterval( fn , miliseconds )
From MDC docs:
Summary
Calls a function repeatedly, with a fixed time delay between each call to that function.
Syntax
var intervalID = window.setInterval(func, delay[, param1, param2, ...]);
var intervalID = window.setInterval(code, delay);
where
intervalID is a unique interval ID you can pass to clearInterval().
func is the function you want to be called repeatedly.
code in the alternate syntax, is a string of code you want to be executed repeatedly. (Using this syntax is not recommended for the same reasons as using eval())
delay is the number of milliseconds (thousandths of a second) that the setInterval() function should wait before each call to func. As with setTimeout, there is a minimum delay enforced.
Note that passing additional parameters to the function in the first syntax does not work in Internet Explorer.
Example
// alerts "Hey" every second
setInterval(function() { alert("Hey"); }, 1000);
setInterval(function(){
// your code...
}, 4000);
It's not too hard in javascript.
// declare your variable for the setInterval so that you can clear it later
var myInterval;
// set your interval
myInterval = setInterval(whichFunction,4000);
whichFunction{
// function code goes here
}
// this code clears your interval (myInterval)
window.clearInterval(myInterval);
Hope this helps!
Another possibility is to use setTimeout, but place it along with your code in a function that gets called recursively in the callback to the $.get() request.
This will ensure that the requests are a minimum of 4 seconds apart since the next request will not begin until the previous response was received.
// v--------place your code in a function
function get_request() {
$.get("request2.php", function(vystup){
if (vystup !== ""){
$("#prompt").html(vystup)
.animate({"top": "+=25px"}, 500)
.delay(2000)
.animate({"top": "-=25px"}, 500)
.delay(500)
.html("");
}
setTimeout( get_request, 4000 ); // <-- when you ge a response, call it
// again after a 4 second delay
});
}
get_request(); // <-- start it off
const milliseconds = 4000
setInterval(
() => {
// self executing repeated code below
}, milliseconds);
Call a Javascript function every 2 second continuously for 20 second.
var intervalPromise;
$scope.startTimer = function(fn, delay, timeoutTime) {
intervalPromise = $interval(function() {
fn();
var currentTime = new Date().getTime() - $scope.startTime;
if (currentTime > timeoutTime){
$interval.cancel(intervalPromise);
}
}, delay);
};
$scope.startTimer(hello, 2000, 10000);
hello(){
console.log("hello");
}

Calling a function that is a clock from within another function accelerates the clock

I have three function: the first is a clock with setTimeout within, the second is a function called when the clock reach zero with a setInterval within and the third is a function called when the setInterval of the second is cleared and set another interval that when is cleared call the clock again. The chain of functions work but accelerate the clock a lot and I don't know why.
var secs=8;
function clock(){
secs--;
var timer=setTimeout(clock,1000);
document.getElementById('clock').innerHTML = 'Clock: ' + secs;
if(secs==0){
clearTimeout(timer);
noEvent();
}
}
function noEvent(){
var count=10;
var timer1=setInterval(function(){
// do something
count--;
if(count==0){
clearInterval(timer1);
repetition();
}
},200)
}
function repetition(){
var count=3;
var timer2=setInterval(function(){
// do something
count--;
if(count==0){
clearInterval(timer2);
secs=8;
clock();
}
},1000)
}
var index=0;
$("myId").click(function(){
var rand=this.id;
var check=(arrComputer[index]==rand); // arrComputer is an array
// generated by the computer
// by other function
if(check==true) {
// do something
clock();
}
}
The functions and the calls work but the clock that is set to 1 second (setTimeout(clock,1000)) go to one second in the first call, but in successives go much faster, so the variable secs go 8,7,6,5,...,0 but to a bigger speed: between 8 and 7 there is not 1000ms but may be 200ms.

Javascript - Pausing an IIFE output that has setTimeout and displays min/sec - Pomodoro Clock

I have two functions that display minutes and seconds. Inside the functions I'm using an IIFE with a setTimeout to calculate the time. After getting this, having a hard time figuring out how I could pause the display if pause button is clicked.
The timer works fine and displays correctly.
I realize this is probably not a good way to do it, but I spent so much time (trying to learn how to use IIFE) that I don't want to give up. If I have to, then I will scratch it.
Update - This timer will be getting input from the user. It might be 25 minutes. I want it to start counting down from there until it reaches 0, and the user able to pause at anytime.
let convertToSeconds = document.getElementById('timeValue').value * 60;
let seconds = 60;
function secondsCounter(time) {
// let flag = document.getElementById('pauseButton').value;
for (let i = seconds; i > 0; i--) {
(function(x) {
setTimeout(function() {
let remaining = seconds - x;
document.getElementById('displaySeconds').innerHTML = remaining;
console.log(remaining);
}, i * 1000);
})(i);
}
}
function counter() {
for (let i = convertToSeconds; i > 0; i--) {
(function(minutes) {
setTimeout(function() {
let remaining = Math.floor((convertToSeconds - minutes) / 60);
document.getElementById('displayMinutes').innerHTML = remaining;
console.log(remaining);
}, i * 1000);
setTimeout(function() {
secondsCounter(seconds);
}, i * 60000);
})(i);
}
secondsCounter(seconds);
}
I've tried a couple of things.
Using a flag and if statement around document.getElementById('displaySeconds').innerHTML = remaining; so if my pause button is clicked, the flag changes, and another setTimeout (10 minutes) is triggered. Doesn't stop the countdown on the DOM, it keeps going. I just wanted to see some reaction, but nothing happened. Something like:
function secondsCounter(time) {
let flag = document.getElementById('pauseButton').value;
for (let i = seconds; i > 0; i--) {
(function(x) {
setTimeout(function() {
let remaining = seconds - x;
if (flag === 'yes') {
document.getElementById('displaySeconds').innerHTML = remaining;
console.log(remaining);
} else {
setTimeout(function() {
console.log(remaining);
}, 10000);
}
}, i * 1000);
})(i);
}
}
Using a setInterval and clearInterval that didn't do anything.
Is this possible? Not sure where else to look. Thank you
You can't stop/pause a setTimeout or clearTimeout without making a reference to the timer, storing it and then calling clearTimeout(timer) or clearInterval(timer).
So, instead of: setTimeout(someFunciton)
You need: timer = setTimeout(someFunciton)
And, the timer variable needs to be declared in a scope that is accessible to all functions that will use it.
See setTimeout() for details.
Without a reference to the timer, you will not be able to stop it and that's caused you to go on a wild goose chase for other ways to do it, which is overthinking what you actually need.
In the end, I think you should just have one function that does all the counting down so that you only have one timer to worry about.
Lastly, you can use the JavaScript Date object and its get / set Hours, Minutes and Seconds methods to take care of the reverse counting for you.
(function() {
// Ask user for a time to start counting down from.
var countdown = prompt("How much time do you want to put on the clock? (hh:mm:ss)");
// Take that string and split it into the HH, MM and SS stored in an array
var countdownArray = countdown.split(":")
// Extract the individual pieces of the array and convert to numbers:
var hh = parseInt(countdownArray[0],10);
var mm = parseInt(countdownArray[1],10);
var ss = parseInt(countdownArray[2],10);
// Make a new date and set it to the countdown value
var countdownTime = new Date();
countdownTime.setHours(hh, mm, ss);
// DOM object variables
var clock = null, btnStart = null, btnStop = null;
// Make a reference to the timer that will represent the running clock function
var timer = null;
window.addEventListener("DOMContentLoaded", function () {
// Make a cache variable to the DOM element we'll want to use more than once:
clock = document.getElementById("clock");
btnStart = document.getElementById("btnStart");
btnStop = document.getElementById("btnStop");
// Wire up the buttons
btnStart.addEventListener("click", startClock);
btnStop.addEventListener("click", stopClock);
// Start the clock
startClock();
});
function startClock() {
// Make sure to stop any previously running timers so that only
// one will ever be running
clearTimeout(timer);
// Get the current time and display
console.log(countdownTime.getSeconds());
countdownTime.setSeconds(countdownTime.getSeconds() - 1);
clock.innerHTML = countdownTime.toLocaleTimeString().replace(" AM", "");
// Have this function call itself, recursively every 900ms
timer = setTimeout(startClock, 900);
}
function stopClock() {
// Have this function call itself, recursively every 900ms
clearTimeout(timer);
}
}());
<div id="clock"></div>
<button id="btnStart">Start Clock</button>
<button id="btnStop">Stop Clock</button>

Categories

Resources