How to make the refresh frequency of setTimeout a variable? - javascript

I want a function I am writing to call itself automatically. I want to be able to parse the frequency at which it calls itself via the first time I parse it. It would then use that same value internally with the JS setTimeout() function to call itself repeatedly again at the same frequency.
So you can see what I have in the sample below:
function testFunction(refreshFrequ){
setTimeout(function() {
console.log("frequency: "+refreshFrequ);
testFunction(refreshFrequ);
}, refreshFrequ);
}
// run the 1st time
testFunction(5000);
The problem is that this doesn't work as from the second time it runs onwards the parsed timeout isn't evaluated. The console output gives a clue to what's going on here:
frequency: undefined
How would I get this working, nothing so far has helped.

Try Window setInterval() Method instead. Also see this answer and this answer for more information.
var autoInterval;
var elapsed = 0;
function myStartFunction(refreshFrequ) {
if (!autoInterval) {
autoInterval = setInterval(function() {
elapsed++;
document.getElementById("txt").innerHTML = refreshFrequ * elapsed + " elapsed.";
console.log("frequency interval: " + refreshFrequ + " x " + elapsed);
}, refreshFrequ);
}
}
function myStopFunction() {
if (autoInterval) {
clearInterval(autoInterval);
autoInterval = null;
elapsed = 0;
document.getElementById("txt").innerHTML = "Interval was reset.";
console.log("interval stopped");
}
}
myStartFunction(5000);
<p>The setInterval() method has started automatically.</p>
<button onclick="myStartFunction(1000)" title="Start with 1000 ms interval. Clicking this button while the event is active should not create a new interval instance.">Start</button> <button onclick="myStopFunction()" title="Click to stop and clear the interval instance.">Stop</button>
<p id="txt">0 elapsed.</p>
Edit: Although there was no mention of the potential duplicate function calls, the other answer should be taken into consideration, especially if the event can arbitrarily be executed. The if statement was imposed in order to prevent duplicate events from being stacked up against the original instance; otherwise, each additionally executed function would result in a unique instance, which could then further create unstoppable multiple events, so I must give credit where credit is due. Kudos to Tymek!

You might want to use setInterval instead.
var testFunction = (function () { // This will "build"/"enclose" our function
var handle = null; // ID of the interval
return function (freq) {
if (handle !== null) clearInterval(handle);
handle = setInterval(function() {
console.log("frequency: " + freq);
}, freq);
};
})();
With this if you re-initialize interval, you will not create another instance of it (having 2 functions ticking).
You can learn more about setInterval at: https://www.w3schools.com/jsref/met_win_setinterval.asp
and more about how JavaScript functions works at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

Related

JS Func. logs message with time interval

Was hoping to find some help complete this question.
logs the message parameter to the console every (Number Parameter). Implement an html button to start and stop this sequence.
In attempting the question I was able to get this so far.
var displayLog = function Container(param) {
var message = 'any string'; // Local message variable
var timeCount = "10"; // Local time count variable
setInterval(function getLoggeddemo(message,timeCount) {
console.log(message);
return getLoggeddemo;
}(), timeCount);
}
The question is asking to display a message every (x) seconds, when a button is toggled between start & stop. I'm currently trying to figure out how to include an if/else statement to start and stop the sequence with an Html button .
A few issues:
Don't call the function you want to pass to to setInterval: so remove the parentheses after the function body.
You never seem to call displayLog.
timeCount is supposed to be a number, not a string: it is the number of milliseconds the interval lasts.
There is no influence of the button clicks on the interval logic.
Returning something in a setInterval callback has no meaning. Also the arguments will not be provided to that callback: remove those parameters.
I would suggest not to add/remove event listeners, but to use a boolean variable that indicates the state you are in, and depending on that perform the appropriate action in one, single click handler:
var i = 0;
var displayLog = function Container(message) {
console.log(i++, message);
// Return the id of the interval
return setInterval(function getLoggeddemo() { // no arguments here
console.log(i++, message);
}, 1000); // Every second
}
var mixBut = document.getElementById("mixBut");
var interval = null;
mixBut.addEventListener("click", toggle);
function toggle(){
if (interval === null) {
mixBut.value = "Stop";
interval = displayLog("Hi there!");
} else {
mixBut.value = "Start";
clearInterval(interval);
interval = null;
}
}
<button id="mixBut">Mix</button>

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

Run javascript function and stop either after 5 seconds or condition is met?

I need to write in a pure JavaScript function which will execute only for 5 seconds and will stop if either one of the following conditions (whichever comes first)
5 seconds has elapsed
user inputted a field
I could only do condition 2 but can't figure out how to break the loop after 5 seconds:
function beginScanningForItemVer2(){
var userInput= false;
var element;
while (!userInput){
element = document.getElementById("input").value;
if (element != null){
userInput= true;
}
}
}
EDIT:
Thanks guys for helping me. Please keep helping me...
It seems I cannot use a while loop for detecting user input because my CPU usage goes up really fast while on the loop. Is there any way to accomplish both of these? Please help me
Javascript tends to be very callback oriented, since by default all the Javascript on a page runs in a single thread, which means that the UI isn't responsive while other code is busy running. So rather than looping in a function and looking for input on each loop, you likely want to register a callback function which will be called when your input element experiences a change -- for example, the onchange listener will run your callback whenever the value of the element changes. You could unregister this callback 5 seconds later to stop anything from happening if the user inputs something after the 5 seconds are up.
Sparse example (referencing http://www.w3schools.com/jsref/event_onchange.asp):
// Set a function to be called when the value of the input element changes.
object.onchange = function() {
valueAfterChange = document.getElementById("input").value;
// Do something with valueAfterChange.
}
// window.setInterval calls a function after a set delay.
window.setInterval(function() {
object.onchange = null;
// Anything else you might want to do after 5 seconds.
}, 5000); // Call this function after 5000 milliseconds == 5 seconds.
If this is still an active issue, maybe you could try this:
const endTime = Date.now() + 5000; // set your cutoff
const scanning = setInterval(() => {
const element = document.getElementById('input').value;
if (element) {
clearInterval(scanning);
}
if (endTime < Date.now()) {
clearInterval(scanning);
}
}, 1000 /* interval in ms */)
Where you set an interval to scan every second (or however often you want), and then you can set a condition to stop the interval if it passes the 5 second mark.
Eddited
You could combine setInterval and setTimeout to solve . Your code will look like this.
var interval = setInterval(function() {
var userInput= false;
var element;
while (!userInput){
element = document.getElementById("input").value;
if (element != null){
userInput= true;
}
}
}, 1000);
setTimeout(function() {
clearInterval(interval);
}, 5000)
You could see more information here. Cheers.
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers

Wait before a javascript function can be called again

I've looked at many different solutions to this, none of which worked. I know it has something to do with setTimeout, but I don't know how to implement it properly.
function myfunction()
{
//the function
//wait for 1 second before it can be ran again
}
To clarify: I don't want to call the function at a regular interval, I want to be able to enforce a delay before the function can be called again.
var lastTime = 0;
function myFunction() {
var now = new Date().getTime(); // Time in milliseconds
if (now - lasttime < 1000) {
return;
} else {
lastTime = now;
}
// rest of function
}
You don't need to use setTimeout at all. The following is similar to other answers, but uses a closure to remember the last time the function ran rather than a global variable.
var myFunction = function() {
var lastTime = new Date();
return function() {
var now = new Date();
if ((now - lastTime) < 1000) return;
lastTime = now;
/* do stuff */
};
}());
I think the easiest solution would be to hold a boolean variable and reset it to true after a given delay.
fiddle
HTML
<button id="clickme">click me!</button>
JavaScript
var canGo = true,
delay = 1000; // one second
var myFunction = function () {
if (canGo) {
canGo = false;
// do whatever you want
alert("Hi!");
setTimeout(function () {
canGo = true;
}, delay)
} else {
alert("Can't go!");
}
}
$("#clickme").click(function(){
myFunction();
})
With this, you hold a boolean, canGo, and set it to true. If the function is run, it sets canGo to false and sets a setTimeout() for a time period of delay, in milliseconds. If you try to run the function again, it won't run and will, instead, alert("Can't go!"). This was just for demonstrative purposes; you don't need that part. After delay, canGo will be set to true, and you will be able to once more run the function.
var lastRan = 0;
var myFunction = function() {
var now = Date.now();
if(now-lastRan < 1000) {
return;
}
lastRan = now;
//rest of function
};
You may want to use throttle or debounce from underscore.js
http://underscorejs.org/#throttle
throttle_.throttle(function, wait, [options])
Creates and returns a
new, throttled version of the passed function, that, when invoked
repeatedly, will only actually call the original function at most once
per every wait milliseconds. Useful for rate-limiting events that
occur faster than you can keep up with.
By default, throttle will execute the function as soon as you call it
for the first time, and, if you call it again any number of times
during the wait period, as soon as that period is over. If you'd like
to disable the leading-edge call, pass {leading: false}, and if you'd
like to disable the execution on the trailing-edge, pass {trailing:
false}.
var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);
http://underscorejs.org/#debounce
debounce_.debounce(function, wait, [immediate])
Creates and returns a
new debounced version of the passed function which will postpone its
execution until after wait milliseconds have elapsed since the last
time it was invoked. Useful for implementing behavior that should only
happen after the input has stopped arriving. For example: rendering a
preview of a Markdown comment, recalculating a layout after the window
has stopped being resized, and so on.
Pass true for the immediate parameter to cause debounce to trigger the
function on the leading instead of the trailing edge of the wait
interval. Useful in circumstances like preventing accidental
double-clicks on a "submit" button from firing a second time.
var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);
If you just want to run your function again after a set time, you can use setTimeout and pass it the function to run and the delay period in milliseconds.
function myfunction() {
//the function
//run again in one second
setTimeout(myfunction, 1000);
}
Edited based on poster's comments:
var waiting = false;
var myfunction = function() {
if (!waiting) {
//Run some code
waiting = setTimeout(function() {
waiting = false;
}, 1000);
}
};

Timing in JS - multiple setIntervals running at once and starting at the same time?

Let's say I have a function:
myFunc = function(number) {
console.log("Booyah! "+number);
}
And I want it to run on a set interval. Sounds like I should use setInterval, huh!
But what if I want to run multiple intervals of the same function, all starting at the exact same time?
setInterval(function(){
myFunc(1);
}, 500);
setInterval(function(){
myFunc(2);
}, 1000);
setInterval(function(){
myFunc(3);
}, 2000);
So that the first runs exactly twice in the time it takes the second to run once, and the same between the second and third.
How do you make sure that they all start at the same time so that they are in sync?
Good question, but in JS you can't. To have multiple functions in the same program execute at the same time you need multi-threading and some deep timing and thread handling skills. JS is single threaded. setInterval doesn't acutally run the function after the delay, rather after the delay it adds the function to the event stack to be run as soon as the processor can get to it. If the proc is busy with another operation, it will take longer than the delay period to actually run. Multiple intervals/timeouts are all adding calls to the same event stack, so they run in turn as the proc is available.
function Timer(funct, delayMs, times)
{
if(times==undefined)
{
times=-1;
}
if(delayMs==undefined)
{
delayMs=10;
}
this.funct=funct;
var times=times;
var timesCount=0;
var ticks = (delayMs/10)|0;
var count=0;
Timer.instances.push(this);
this.tick = function()
{
if(count>=ticks)
{
this.funct();
count=0;
if(times>-1)
{
timesCount++;
if(timesCount>=times)
{
this.stop();
}
}
}
count++;
};
this.stop=function()
{
var index = Timer.instances.indexOf(this);
Timer.instances.splice(index, 1);
};
}
Timer.instances=[];
Timer.ontick=function()
{
for(var i in Timer.instances)
{
Timer.instances[i].tick();
}
};
window.setInterval(Timer.ontick, 10);
And to use it:
function onTick()
{
window.alert('test');
}
function onTick2()
{
window.alert('test2');
}
var timer = new Timer(onTick, 2000,-1);
var timer = new Timer(onTick2, 16000,-1);
For a finite number of ticks, change the last parameter to a positive integer for number. I used -1 to indicate continuous running.
Ignore anyone who tells you that you can't. You can make it do just about any thing you like!
You can make something like this.
arr = Array();
arr[0] = "hi";
arr[1] = "bye";
setTimer0 = setInterval(function(id){
console.log(arr[id])
},1000,(0));
setTimer1 = setInterval(function(id){
console.log(arr[id]);
},500,(1));
Hope it helps!
JavaScript is single threaded. You can use html5 web worker or try using setTimeout recursively. Create multiple functions following this example:
var interval = setTimeout(appendDateToBody, 5000);
function appendDateToBody() {
document.body.appendChild(
document.createTextNode(new Date() + " "));
interval = setTimeout(appendDateToBody, 5000);
}
Read this article:
http://weblogs.asp.net/bleroy/archive/2009/05/14/setinterval-is-moderately-evil.aspx
You can use multiples of ticks inside functions, in the example below you can run one function every 0.1 sec, and another every 1 sec.
Obviously, the timing will go wrong if functions require longer times than the intervals you set. You might need to experiment with the values to make them work or tolerate the incorrect timing.
Set a variable to handle tick multiples
let tickDivider = -1
Increase the value of tick variable inside the faster function
const fastFunc = ()=> {
tickDivider += 1
console.log('fastFunciton')
}
Use a condition to on running the slower function
const slowFunc = ()=> {
if (!(tickDivider % 10)){
console.log('slowFunction')
}
}
Call both functions in a single one. The order is not important unless you set tickDivider to 0 (of any multiple of 10)
const updateAllFuncs = () => {
fastFunc()
slowFunc()
}
Set the interval to the frequency of the faster function
setInterval(updateAllFuncs, 100)
What I'm doing here is adding a speed attribute to the HTML elements. These speeds are passed as a parameter to setCounter(). I did this mainly to make the code easier to test and play with.
The function setCounter() is invoked inside a loop for every HTML element with class counter. This function sets a new setInterval in every execution.
The intervals seem to be working in sync.
const elements = document.querySelectorAll('.counter')
elements.forEach((el, i) => {
let speed = Number(elements[i].getAttribute('speed'))
setCounter(el, speed, 5000)
})
function setCounter(element, speed, elapse){
let count = 0
setInterval(() => {
count = (count >= elapse) ? elapse : count + speed
if(count === elapse) clearInterval()
element.innerHTML = count
}, 1)
}
Same Speeds
<p class="counter" speed='10'></p>
<p class="counter" speed='10'></p>
Different Speeds
<p class="counter" speed='3'></p>
<p class="counter" speed='5'></p>

Categories

Resources