can't stop this recursive settimeout function in nodejs - javascript

I made this recursive set timeout function to send time for each game room but when the time finishes i cannot stop the function. i tried the clear timeout but it did not help so if anyone would help me.
setTimeout(function GameTime() {
io.in(Rooms[picked].name).emit('PlayTime', timeleft);
timeleft.x--; // HERE WHERE I DECREMENT THE TIME
setTimeout(GameTime, 1000)
}, 1000)

Assuming you're not stopping the loop, you has to stop it using the function clearTimeout.
A better approach for your scenario is using the function setInterval:
var x = 3;
var intervalId = setInterval(function GameTime() {
//io.in(Rooms[picked].name).emit('PlayTime', timeleft);
//timeleft.x--; // HERE WHERE I DECREMENT THE TIME
x--;
if (x < 0) {
clearInterval(intervalId);
console.log('finished!');
return;
}
console.log('looping!');
}, 1000)

You need a reference to the setTimeout you want to clear:
let timeoutId, gameTimeoutId
timeoutId = setTimeout(function GameTime() {
console.log('GameTime')
gameTimeoutId = setTimeout(GameTime, 1000)
}, 1000)
setTimeout(function GameTime() {
clearTimeout(timeoutId)
clearTimeout(gameTimeoutId)
}, 5000)
This snippet will call GameTime each 1 second and after 5 seconds it removes the interval loop
As an alternative to this is to use setInterval, this will simplify you code considerable:
const intervalId = setInterval(() => {
console.log('GameTime')
// do stuff
}, 1000)
setTimeout(() => {
clearInterval(intervalId)
}, 5000)

Related

Function only executes once in for loop

I have a function that starts a timer that can be paused. Now I want several timers to run after each other, for this I decided to use a for loop.
However, when I call the function inside the loop, even though the loop goes n (5 in this case) times, the function only executes once, while the console.log executes 5 times as intended. What am I doing wrong here?
var timer = null;
const resetTimer = () => {
clearInterval(timer);
timer = null;
}
function trigger (startTime, endTime, sets){
for (let i = 0; i < sets; i++){
myTimer(startTime, endTime, sets);
console.log("1")
}
}
function myTimer (startTime, endTime, sets){
if (!timer) {
timer = setInterval(function() {
display.innerHTML = hhmmss(++startTime);
if (startTime >= endTime) {
resetTimer();
}
}, 1000);
}
}
Your function is called every time, but in all of the calls after the first one, if (!timer) is false, so it doesn't do anything.
If you want multiple timers, you'll need multiple places to store the timer handle. For instance, in a local within myTimer:
// No global `timer`
// Accept the timer to clear (no real reason for this function if all it does is `clearInterval`)
const resetTimer = (timer) => {
clearInterval(timer);
};
function trigger (startTime, endTime, sets){
for (let i = 0; i < sets; i++){
myTimer(startTime, endTime, sets);
}
}
function myTimer(startTime, endTime, sets) {
// There's a different `timer` for each call to `myTimer`
const timer = setInterval(function() {
display.innerHTML = hhmmss(++startTime);
if (startTime >= endTime) {
// Pass this timer's `timer` to `resetTimer`
resetTimer(timer);
}
}, 1000);
}
You've used if (!timer) { so on the first iteration it will assign something to timer and after that nothing inside that if will execute again.

How can I postpone setInterval if a condition is met?

This is my script:
var find = setInterval(function() {
if (document.getElementsByClassName('RDlrG Inn9w iWO5td')[0]) {
if (document.getElementsByClassName('w1OTme')[0]) {
window.open(document.getElementsByClassName('w1OTme')[0].href);
//here I call the setTimeout function for my SetInterval
}
}
}, 2000);
This is a Tampermonkey script I am developing for Google Calendar.
I want to set a timeout function on my find function aka setInterval function so it doesn't spam the window.open function.
In short:
Is there a way I could set a Timeout function on setInterval function which is called from my setInterval function?
If yes, how so?
You can't pause the interval of a setInterval, but you can stop it and start it again after some time.
let find = null;
function intervalFunc() {
if (condition) {
// Do some operations which should not be repeated for the next 30 seconds
// Clear current interval
clearInterval(find);
// Schedule to start the setInterval after 30 seconds.
setTimeout(function() {
find = setInterval(intervalFunc, 2000);
}, 30000 - 2000);
// ^
// Subtracting the interval dalay to cancel out the delay for the first invocation.
// (Because the first invocation will also wait for 2 seconds, so the pause would be 32 seconds instead of 30)
}
}
// Start the initial setInterval
find = setInterval(intervalFunc, 2000);
Here is a working example:
let count = 0;
const intervalDelay = 200;
const pauseDelay = 3000;
let find = null;
function intervalFunc() {
count++;
console.log('check', count);
if (count >= 5) {
count = 0;
console.log('Pausing for ' + (pauseDelay / 1000) + ' seconds');
clearInterval(find);
setTimeout(function() {
find = setInterval(intervalFunc, intervalDelay);
}, pauseDelay - intervalDelay);
}
}
find = setInterval(intervalFunc, intervalDelay);

How to stop a function after ten seconds?

I found this piece of code while trying to find out a way to load a reddit page so that I can use ctrl + f to find a specific post. The problem is that it just keeps scrolling down and loading the pages. I need to find a way to stop it after 10 seconds so that I can take a look at what I loaded. Also I don't know any javascript so I couldn't really find anythig that would help me.
Here is the code
var lastScrollHeight = 0;
function autoScroll() {
var sh = document.documentElement.scrollHeight;
if (sh != lastScrollHeight) {
lastScrollHeight = sh;
document.documentElement.scrollTop = sh;
}
}
window.setInterval(autoScroll, 100);
I just paste that into the firefox console.
The setInterval() function returns an ID, which you can use to stop it.
Just put it in setTimeout() method like this:
var myInterval = setInterval(autoscroll, 100);
setTimeout(function(){ clearInterval(myInterval); }, 10000);
To stop the interval after a certain amount of time use a setTimeout() that calls clearInterval(). Here's a simplified version (with the time reduced to 1 second for demo purposes) that should help:
function autoScroll(){
console.log("running")
}
// save a reference to the interval handle
let interval = window.setInterval(autoScroll, 100);
// cancel interval after 1 second (1000 ms)
setTimeout(() => clearInterval(interval), 1000)
You will simply need to call clearInterval on your looped function to stop it after using a setTimeout set to 10 seconds, here is how you can implement it :
var lastScrollHeight = 0;
function autoScroll() {
var sh = document.documentElement.scrollHeight;
if (sh != lastScrollHeight) {
lastScrollHeight = sh;
document.documentElement.scrollTop = sh;
}
}
const interval = window.setInterval(autoScroll, 100);
window.setTimeout(() => {clearInterval(interval)}, 10000);
....
var intervalID = window.setInterval(autoScroll, 100);
setTimeout(function(){
clearInterval(intervalID);
}, 10000);
You can use setTimeout to call the function until 10s are up.
Here's an immediately-invoked function that calls itself every 100th sec until 10s has been reached.
(function autoScroll(t) {
t = t || 0;
if (t < 10000) {
console.log(t);
setTimeout(autoScroll, 100, t += 100);
}
})();

timer with delay, reset and restart? jQuery

So I basically have a timer which counts 1 number every 4 seconds.
It stops when it hits 10.
Q: How do i make it so that the timer stops at 10 for a couple of seconds, then starts counting again at 1?
var i = 8;
setInterval( increment, 4000);
function increment(){
if(i<=10)
{
console.log(i);
$('.increase').html('').append(i);
i++;
}
}
JSfiddle: http://jsfiddle.net/0t3s8erj/
Use the else!
var counter = 0
function increment () {
counter++
if (counter <= 10) {
console.log(counter)
} else {
clearInterval(incrementInterval)
setTimeout(function () {
incrementInterval = setInterval(increment, 4000)
}, 10000)
}
}
incrementInterval = setInterval(increment, 4000)
You can do it like this where you run an interval timer until you get to the max count, then you clear that timer and start a new timer for the amount of time you want to pause and then when that delay timer fires, you call your function again to start it all over.
Here's a working code snippet (I set the times short here for demo purposes, but you can set them to whatever you want):
function runTimer(selector, start, end, interval, delay) {
var cntr = start;
$(selector).html(cntr);
var timer = setInterval(function() {
++cntr;
$(selector).html(cntr);
if (cntr >= end) {
clearInterval(timer);
setTimeout(function() {
runTimer(selector, 1, end, interval, delay);
}, delay);
}
}, interval);
}
runTimer('.increase', 8, 10, 300, 2000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="increase">8</span>/10

Javascript - telling setInterval to only fire x amount of times?

Is it possible to limit the amount of times that setInterval will fire in javascript?
You can call clearInterval() after x calls:
var x = 0;
var intervalID = setInterval(function () {
// Your logic here
if (++x === 5) {
window.clearInterval(intervalID);
}
}, 1000);
To avoid global variables, an improvement of the above would be:
function setIntervalX(callback, delay, repetitions) {
var x = 0;
var intervalID = window.setInterval(function () {
callback();
if (++x === repetitions) {
window.clearInterval(intervalID);
}
}, delay);
}
Then you can call the new setInvervalX() function as follows:
// This will be repeated 5 times with 1 second intervals:
setIntervalX(function () {
// Your logic here
}, 1000, 5);
I personally prefer to use setTimeout() spaced out to achieve the same effect
// Set a function to run every "interval" seconds a total of "x" times
var x = 10;
var interval = 1000;
for (var i = 0; i < x; i++) {
setTimeout(function () {
// Do Something
}, i * interval)
}
There's no clean up required with clearInterval()
You can enclose it to avoid variables leaking and it looks pretty clean :)
// Definition
function setIntervalLimited(callback, interval, x) {
for (var i = 0; i < x; i++) {
setTimeout(callback, i * interval);
}
}
// Usage
setIntervalLimited(function() {
console.log('hit'); // => hit...hit...etc (every second, stops after 10)
}, 1000, 10)
You can set a timeout that calls clearInterval.
This should work:
function setTimedInterval(callback, delay, timeout){
var id=window.setInterval(callback, delay);
window.setTimeout(function(){
window.clearInterval(id);
}, timeout);
}
You can use setTimeout and a for loop.
var numberOfTimes = 20;
delay = 1000;
for (let i = 0; i < numberOfTimes; i++) {
setTimeout( doSomething, delay * i);
}
This will clear the interval after 10 calls
<html>
<body>
<input type="text" id="clock" />
<script language=javascript>
var numOfCalls = 0;
var int=self.setInterval("clock()",1000);
function clock()
{
var d=new Date();
var t=d.toLocaleTimeString();
document.getElementById("clock").value=t;
numOfCalls++;
if(numOfCalls == 10)
window.clearInterval(int);
}
</script>
</form>
</body>
</html>
I made a small package that does this for NodeJS.
https://www.npmjs.com/package/count-interval
It's a drop-in replacement for setInterval (including parameter passing), but it takes an additional count parameter. This example prints a message once every second, but only 3 times.
const countInterval = require('./countInterval');
const timer = countInterval(() => {
console.log('fired!', new Date());
}, 1000, 3);
And for those of you preferring setTimeout and loving recursion here is my suggestion ;)
const setIntervalX = (fn, delay, times) => {
if(!times) return
setTimeout(() => {
fn()
setIntervalX(fn, delay, times-1)
}, delay)
}
Then as suggested you can call the new setInvervalX() function as follows:
// This will be repeated every for 5 times with 1 second intervals:
setIntervalX(function () {
// Your logic here
}, 1000, 5);
You can do this actually very simply with setTimeout() and an incremental counter.
var i = 0; // counter for the timer
function doSomething() {
console.log("1 second"); // your actual code here, alternatively call an other function here
if (++i < 10)
{ // only reset the timer when maximum of 10 times it is fired
console.log("reset the timer");
setTimeout(doSomething, 1000); // reset the timer
}
}
setTimeout(doSomething, 1000); // init the first
This answer is based on SO: Repeating setTimeout and a nice, neat and tidy small combination with this.
You can use Six
SetIntervalX: Limit the number of times that setInterval will fire
import { setIntervalX } from "https://deno.land/x/six/mod.ts";
import { randomNumber } from "https://deno.land/x/random_number/mod.ts";
const API_URL = "https://leap.deno.dev";
async function checkAPIStatus() {
const startTime = performance.now();
const randomYear = randomNumber({ min: 2000, max: 10_000 });
const response = await fetch(`${API_URL}/${randomYear}`);
const data = await response.json();
console.log(`Is ${randomYear} a leap year? ${data.leapYear}.`);
const entTime = performance.now();
console.log(`Request took ${(entTime - startTime) / 1000} seconds.`);
}
setIntervalX(checkAPIStatus, 2000, 15);
Web Page: https://ulti.js.org/six
Repository: https://github.com/UltiRequiem/six
It includes documentation, 100% code coverage, and examples!
Works on Deno, Node.js and the browser!

Categories

Resources