Send variable to the same function - javascript

I want a function that looks for elements with the "comment" class, and if the number of comments has changed, (if there is a new comment) it will call an other function. So this is what I did:
function main(num0){
var comments = document.getElementsByClassName("comment");
var num = comments.length;
if (num!=num0){
//function to call();
console.log("New Comment");
}
setTimeout(main(num),10); //check every 10 for new comments
}
main(0);
num0 is the number of comments the last time the function was called so I try to recall the same function but num0 takes the value of num, but it doesn't seems to work.

I recommend using setInterval. calling recursion at higher rate may cause different errors after some time.
let num = 0;
setInterval(()=>{
var comments = document.getElementsByClassName("comment");
var num1 = comments.length;
if (num!=num1){
//function to call();
console.log("New Comment");
num=num1
}
},10)

Your use of setTimeout is invalid; you are calling the function main instead of providing setTimeout with a callback. I also believe you need to pass num0 instead of num in your timeout.
Try this:
function main(num0){
var comments = document.getElementsByClassName("comment");
var num = comments.length;
if (num!=num0){
//function to call();
console.log("New Comment");
}
setTimeout(main, 10, num0); // Changed this line
}
main(0);
Review this regarding the setTimeout function:
https://www.w3schools.com/jsref/met_win_settimeout.asp

setTimeout takes a function reference. In your case you aren't passing the reference, you are passing the result of that function by calling it.
Example of syntax that does what you intend it to do:
setTimeout(() => main(num),10); //check every 10 for new comments
https://www.w3schools.com/jsref/met_win_settimeout.asp

Related

What is happening to my setTimeout function?

I am trying to make a function(next) that takes a function and a wait time as its arguments. It will then have a counter that will be increased by the function calls.
var up = function() {
var counter = 0;
return counter += 1;
};
var next = function(fn, wait) {
var total = 0; //set total variable to 0
var x = fn(); //call the function and set answer to a variable
total+=x; //add the answer to the total
var n = setTimeout(function(){fn();}, wait);
//THIS BIT DOES NOT GIVE ME 1? Instead I get any number from 16 (depenging on how many times I call it! It increases as I keep calling the function....?!)
total += n;
return total;
};
next(up,1000);
I am totally confused as to why setTimeout is working like this?!
I have looked around for an answer for this and have not hit lucky- I am sorry if I have missed the question on here if it has been asked before!
I did come across this question and tried putting the variable counter outside, however this did not seem to make any difference...
This question seems even closer to the area I am confused about however I am not any closer to comprehending my problem any help would be greatly appreciated as to why the return values that I am getting are so much higher than what I expect them to be..
Another approach that I tried was this:
var next = function(func, wait) {
var storedAnswer = 0;
var answer = function() {
return storedAnswer;
}
var increase = func;
setTimeout(increase, wait);
return answer();
};
next(up, 100); // gives me 0...? the up function here is defined in the above code...
But this ended up with me not getting any movement in the answer...
setTimeout returns the timeout id, not the return value of the callback.
var timeoutID = window.setTimeout(code, [delay]);
Try this:
setTimeout(function(){total += fn();}, wait);
The value that setTimeout returns is an int. But it is also a global counter of timeouts. Which is to say that every timeout shares the same counter. So that you get 16 just means that somewhere, in some part of your page, 15 other timeouts had already executed.
This is perfectly normal to get back an integer of 16 or basically of not 1 in that scenario, and using that integer with a clearTimeout for example will still properly reference the timeout used.
Aside
In node.js (which doesn't seem like what you are using), the mechanism is the same, except that a timeoutObject is returned instead which may still be used to clear the timeout. It is also used for continuations and other server-side related timing mechanisms.
n is the return value of setTimeout, which is a numeric identifier that you can pass to clearTimeout in order to cancel the timeout.
Your basic problem here is that setTimeout simply registers a function to be called after the given delay, and then execution immediately continues to the next line. So this line:
total += n;
is not waiting until your timeout completes. It's happening immediately, and n is, like I said, not the value you want.
You need your next function to take a callback that it can call when the timeout has completed.
var next = function(fn, wait, callback) {
var total = 0;
var x = fn();
total+=x;
setTimeout(function() {
var n = fn();
total += n;
callback(total);
}, wait);
};
You would call it like:
next(up, 100, function(total) {
// This function runs after the operation is done; do something with the total.
});

Calling the setTimeout Function recursively and passing an anonymous function

I am confused on the difference between this syntax:
var timerId;
function clockStart(){
// debugger;
if(timerId){
return;
}
update();
// THIS LINE BELOW *********************************************
var timerId = setTimeout(function(){clockStart()}, 1000);
}
function clockStop(){
timerId = null;
}
function update(){
var date = new Date();
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
if(hours < 10) {
hours = '0'+hours;
}
document.getElementById('hour').innerHTML = hours;
if(minutes < 10){
minutes = 0+minutes;
}
document.getElementById('min').innerHTML = minutes;
if(seconds < 10){
seconds = '0' + seconds;
}
document.getElementById('sec').innerHTML = seconds;
}
I provided both functions being called but the main part of this function I do not understand is why I need to pass an anonymous function to call my clockStart() function.
My function works when I use this syntax:
var timerId = setTimeout(function(){clockStart()}, 1000);
But it doesn't work when I use:
var timerId = setTimeout(clockStart(), 1000);
I have been working a while on these two functions and I honestly stumbled upon this by accident. I really don't see what the anonymous function is doing besides invoking my clockStart function. But in my opinion, my clockStart() function should be invoked every second(1000ms) since it is calling itself, so why does it need an anonymous function to invoke it? Shouldn't it be invoking itself?
If you would like to see this digital 'clock's' full code please checkout my codepen link.
This line:
var timerId = setTimeout(clockStart(), 1000);
is calling clockStart() immediately and passing the return result from that function to setTimeout(). Since the function doesn't return anything, you're effectively doing this:
clockStart();
var timerId = setTimeout(undefined, 1000);
which obviously doesn't do what you want.
You can use this instead:
var timerId = setTimeout(clockStart, 1000);
In this case, you want to pass a function reference to setTimeout() which means you do not include the parens. When you include the parens, that means to execute it NOW. When you just pass the name of the function, that is just a reference to the function (think of it like a handle) by which setTimeout() can call it later. That's what you want.
When you do this:
var timerId = setTimeout(function(){clockStart()}, 1000)
you're just defining an anonymous function and passing a reference to that anonymous function to to setTimeout() which works fine, but is not necessary in this case since you can just pass the clockStart name as in my third code example above.
Since you asked about how a function can call something later, I'll show you a simple example. Here's a function that takes a starting value, an ending value, an increment and a callback function. This will call the callback and pass it the value that it's incrementing until the value exceeds the end value.
// define an increment function that will call a callback
// multiple times based on the start, end and increment arguments
function eachIncrement(start, end, increment, callback) {
// the function argument named callback contains
// a function reference
var val = start;
while (val <= end) {
// execute the function reference and
// pass it the current val
callback(val);
val += increment;
}
}
// define a function that we want to be called later
function processValues(num) {
// this will get called multiple times with
// values 1, 4, 7, 10
}
// set up the increment parameters and pass a function reference
eachIncrement(1, 10, 3, processValues);

A Way To Reset All Timers

My question is: is there a unique way to reset timers without knowing their ID in Javascript? I tried using this code:
var maxId = setTimeout(function(){}, 0);
for(var i=0; i < maxId; i+=1) {
clearTimeout(i);
}
I'm aware this would search for any timer and clear any timer, but nothing happens and I think the console even gives me an error when I use it as a bookmarklet. Also, the value of the timer is stored in innerHTML, as such:
<div id="timer">
<div id="timer-minutes" class="timer-fields">00:00</div>
</div>
A unique way to look at this problem is to override the default functionality of setTimeout. By augmenting the function you can then tap into all uses of setTimeout on the page. Then you can simply create a new method to clear all timeouts.
In the code below, I hot-wire the built-in function (setTimeout) with my own version. As long as this code executes before other scripts on the page, I then can keep track of all invocations of the function on the page. Perhaps you could even store the setTimeouts by callee.
(function(win)
{
var _originalSetTimeout = setTimeout; //Store built-in function
var timers = []; //Maintain a collection of timers
win.setTimeout = function(func, delay) //Hijack the built-in function with your own
{
var timer = _originalSetTimeout(func, delay); //Invoke the built in
timers.push(timer); //Store the timer to your private array
};
win.clearAllTimeouts = function() //Create a new function on the window for resetting all timers
{
for(var i=0,length=timers.length;i<length;i++)
{
win.clearTimeout(timers[i]);
}
};
}(window));
Once this function is wired up you then can test with the following code:
var x=0;
function Test()
{
x++;
console.log('test: ' + x);
setTimeout(Test, 1000);
if(x === 5)
{
clearAllTimeouts();
console.log('all timeouts cleared!');
}
}
Test();
The counter will log up to 5, then once it's it the clearAllTimeouts() function is invoked.
See it in action here:
http://jsbin.com/bulayuro/1/edit

setInterval(setTimeout) function for given invokes javascript

I need to invoke some function given number of times through given delays. How should I do - declare variable for timer and pass it to invoking function for stopping timer in some moment or in loop (n times) invoke setTimeout once ( or some another approach to skeep delay time once) or other.Thanks.
edit to fix syntax eror
var timerID = null;
var n = 5;
this.timerID = setInterval(function(){
funcToInvoke(n,timerID){
if(invokeNumber == n){
clearInterval(timerID);
return;
}
else { do something}
}
},delay)
Yes, the approach is common and better than calling setTimeout in a loop (with a fixed number of times). It is more performant than that and also more flexible, because the interval will be stopped dynamically (might check for a future condition).
However, your code is a bit messy. Fixed:
// Assuming we a have
// n
// delay
// funcToInvoke
// and execute in context of some object
var that = this,
numberOfInvokes = 0;
this.timer = setInterval(function() {
// "this" points to the global object
if (numberOfInvokes == n)
clearInterval(that.timer);
else
funcToInvoke(numberOfInvokes);
numberOfInvokes++;
}, delay);
Your current method has a syntax problem, you can't have a function parameter like this.timerID). In fact, you should remove the whole funcToInvoke declaration, and declare n and timerID as local variables, so they will be available to the closure. Like this:
// Don't forget to define n here!
var n = 5;
// Change timerID to local var instead of property
var timerID = null;
timerID = setInterval(function(){
if(invokeNumber == n){
clearInterval(timerID);
return;
} else {
//do something
}
// You can setTimeout again anywhere in this function if needed
}, delay);
If you want an approximate delay, setInterval is probably ok. If you want a more precise interval, then repeated calls to setTimeout are better as you can adjust the length of time to the next call based on the time since the last call.
E.g. for a clock ticking every second, you can do repeated calls to setTimeout, setting the lag to just after the next full second.

having trouble using setInterval and with random number generation

I'm trying to create a random quote generator. I have created a function called timer that runs another function pickQuote every 400ms but at the moment this doesn't seem to work. in pickQuote I run a function randomNumberGen that creates a random number. My problem in the randomNumberGen is that I want to have an if or if..else in place that checks whether or not the new random number is different from the current quotes[randomNumber] but i'm unsure how to do this.
Can anyone provide me with some insight on how I can achieve this?
My current effort can be viewed here: http://jsbin.com/aqinud/12/edit
index is not defined outside $.each. Variables in functions are not accessible outside it if you use var.
What I recommend is altering the function as follows:
function randomNumberGen() {
//generate randomNumber based on length of array
// round it down (parseInt is for string->number conversion)
var thisRandomNumber = Math.floor(Math.random() * len);
if ( randomNumber === thisRandomNumber ) {
randomNumberGen();
} else {
randomNumber = thisRandomNumber;
}
}
So, first create a random number and only if it's different from randomNumber, update it with the newly created one. Otherwise, try again.
Also, setTimeout requires a function, so don't invoke it yet:
runQuotePicker = setInterval(pickQuote, 400);
http://jsbin.com/aqinud/13/edit
Perhaps something like this:
var currentNumber = -1;
function randomNumberGen() {
var num = parseInt(Math.random() * (len) );
if(currentNumber != num){
currentNumber = num;
return num;
} else {
return randomNumberGen();
}
}
I noticed you had incorrectly passed 'pickQuote' to setInterval. Try wrapping the callback in an anonymous function:
function timer() {
runQuotePicker = setInterval(function(){
pickQuote();
}, 1000);
}
Otherwise you're scheduling the result of pickQuote to be invoked ever x milliseconds.

Categories

Resources