JavaScript: best practices implementation of the setInverval function - javascript

I want to log some text to the console every n number of seconds. My code is:
function logger() {
console.log("log some stuff...");
}
setInterval(logger, 3000);
This works fine. And, the following variation works fine, too:
setInterval(
function logger() {
console.log("log some stuff...";
}, 3000);
Now, I attempt to move setInterval inside the function, as follows:
function logger() {
console.log("log some stuff...");
setInterval(logger, 3000); // moving setInterval here does NOT work
}
This does not work.
Question: Is there a way to move setInverval inside the function? And, if it is possible, is doing so recommended?
Thanks for helping out a JavaScript newbie!
### EDIT ###
Taking the suggestion from #FZs, I implemented the function as follows:
function logger(output, interval) {
var now = new Date()
setInterval(function() {
console.log(output, now.toLocaleString());
}, interval)
}
logger("Foo ", 3000)
The messages are stacking in the console because the Date is not incrementing. Is this a scope issue?

Solved as follows:
function logger(output, interval) {
setInterval(function() {
var now = new Date() // moved this line here!
console.log(output, now.toLocaleString());
}, interval)
}
logger("Foo ", 3000)

Related

Why does setInterval initiate when I'm only assigning it?

I'm assigning to a variable, a function that uses setInterval, but I don't want the function to run until I call it. However, the function is running from just the assignment statement.
sessionClock = setInterval(function() {
console.log("Hi")
}, 1000)
I have also tried like this:
sayHi = function() {
console.log("Hi");
}
var sayHiStarter = setInterval(sayHi, 1000);
Both of these initiate the function and will log "Hi" to the console.
Why is it running on assignment? And what can do I do fix this?
If you only want to bind a function to setInterval, but call it later, you can use bind:
var sessionClock = setInterval.bind(null, function() {
console.log("Hi")
}, 1000);
//... later
var myInterval = sessionClock(); // start the timer
// ... later if you need to clear it
clearInterval(myInterval);
In principle, bind returns a new function that calls your original function (in this case, setInterval) with predefined arguments. So when you call sessionClock, that returned function is called. There a other aspects to bind, but they don't seem to apply in this context.
The call to setInterval does not return a function, but an identification for the created interval. This id is used to remove the interval when you don't want it to execute anymore:
sessionClock = setInterval(function() {
console.log("Hi")
}, 1000)
...
clearInterval(sessionclock);
What you want is something like this:
sessionClock = function () {
return setInterval(function() {
console.log("Hi")
},
1000);
}
//When needed
var intervalId=sessionClock();

Output of one sample program of javascript is giving wrong answer

I was reading one book named 'Hands on node.js' by 'Pedro Teixiera'.
I was trying to execute one same program giving in that book that will call a function and that function is calling the same function recursively within some interval again and again.
But when I executed, it gives only one time '1' and stops
Please help me to figure it out why it is not able to call the same function again.
Sample program is as follows:
var schedule = function(timeout, callbackfunction) {
return {
start: function() {
setTimeout(callbackfunction, timeout)
}
};
};
(function()
{
var timeout = 10000; // 1 second
var count = 0;
schedule(timeout, function doStuff() {
console.log(++ count);
schedule(timeout, doStuff);
}).start(timeout);
})();
You aren't actually calling the function again. start() is the part that starts the timer.
schedule( timeout, function doStuff() {
console.log( ++count );
schedule( timeout, doStuff ).start(); // <--- added .start() here
}).start();
(Also note that the start() function doesn't take parameters.)
with some interval again and again
No, for that you would have used setInterval instead of setTimeout.
it gives only one time '1' and stops
Yes, your doStuff function doesn't put a new timeout. Your odd schedule function needs to be .start()ed!

settimeout being ignore, function is called instantly

function ShowColoursScreen() {
setSquaresList()
$("#ModeOne").hide();
$("#ModeTwo").show();
setTimeout(function () {
$("#ModeOne").show();
$("#ModeTwo").hide();
setTimeout(function () {
ShowColoursScreen();
}, 1500);
}, 15000);
}
This is very very weird, Im wanting to rotated between two divs every 15 seconds (i dont want to use js intervals). However after the first fifteen seconds ShowColoursScreen(); runs without waiting the second 15 seconds (if that makes sense). Its like the timeout gets ignored, any ideas?
Your code is correct. However, the inner timeout just waits for 1.5 seconds as you forgot a zero. Simply replace the 1500 with 15000.
You can also simplify the call a bit - as you do not have any arguments there is no need for the anonymous function: setTimeout(ShowColoursScreen, 15000);
function ShowColoursScreen($elements) {
if(!$elements instanceof jQuery) {
$elements = $($elements);
}
var current = 0;
// What does this function do?
setSquaresList();
function showCurrent () {
var $currentElement = $($elements[current]);
$elements.not($currentElement).hide();
$currentElement.show();
(current++) % $elements.length;
setTimeout(showCurrent, 15000);
}
showCurrent();
return $elements;
}
ShowColoursScreen('#ModeOne, #ModeTwo')

How to clear a javascript timeout thats set within a function

I have a recursive type function in Javascript that runs like this:
function loadThumb(thumb) {
rotate=setTimeout(function() {
loadThumb(next);
}, delay);
}
Note: I've simplified the function to make it easier to read.
I have "a" tags called like this
Load thumb 3
However, they don't clearout the timer, the timer continues to cycle through the function irregardless of the clearTimeout() being called.
Any ideas why? I think it might have something to do with a scope problem or something like that.
Yeah, you need to make rotate a global variable. Simply declare it outside the function like so:
var rotate;
var delay = 1000;
function loadThumb(thumb) {
alert("loading thumb: " + thumb);
rotate = setTimeout(function() {
loadThumb(thumb + 1);
}, delay);
}
Also, you need to make sure you clear the timeout before you call loadThumb. Otherwise you'll clear the timer you just started.
Load thumb 3
fiddle: http://jsfiddle.net/63FUD/
it may be the issue of scope so make rotate as global variable and call clearTimeout(rotate);
refer clearTimeout() example
It may be a scoping issue if you are not declaring rotate externally.
Try this:
var rotate = 0;
function loadThumb(thumb) {
rotate=setTimeout(function() {
loadThumb(next);
}, delay);
}
Return false on the link
Since you are not using var rotate, it should not be a scoping issue since rotate would be in the window scope. Can you show the complete code?
It is considered poor coding to inline the script - you should attach the event handler onload of the page
Also you should not have the setTimeout inside a function that might be called for one image
Try this:
var rotate,next=1;
function loadThumb(thumb) {
if (thumb) ... use thumb
else ... use next
}
function slide() {
rotate=setInterval(function() {
loadThumb();
next++;
if (next>=images.length) next=0;
}, delay);
}
window.onload=function() {
var links = document.getElementsByTagName("a");
if (links[i].className==="thumbLink") {
links[i].onclick=function() {
var idx = this.id.replace("link","");
loadThumb(idx);
clearInterval(rotate);
return false;
}
}
document.getElementById("start").onclick=function() {
slide();
return false;
}
document.getElementById("stop").onclick=function() {
clearInterval(rotate);
return false;
}
slide();
}
assuming
Start
Stop
Show 1
Show 2
Show 3
If you have to manage multiple timeouts, you can use an object in the global scope and some custom methods to create and remove your timeouts. To access the methods you can either put the calls in the onclick handler of your links (like in the example), or use a library like jQuery to bind them.
<script type="text/javascript">
var timeouts = timeouts || {};
function createTimeout(name, milliseconds, callback) {
timeouts.name = setTimeout(callback, milliseconds);
}
function removeTimeout(name) {
if (typeof(timeouts.name) !== undefined) {
clearTimeout(timeouts.name);
timeouts.name = undefined;
}
}
createTimeout('foo', 5000, function() {
alert('timeout')
});
</script>
i have also posted an example on jsFiddle http://jsfiddle.net/AGpzs/
I'm not sure what exactly you are doing, because as far as I can see you didn't post all the code, but this looks better for me:
function loadThumb(thumb) {
return setTimeout(function() {
loadThumb(next);
}, delay);
}
and then:
Load thumb 3

using setTimeout synchronously in JavaScript

I have the following scenario:
setTimeout("alert('this alert is timedout and should be the first');", 5000);
alert("this should be the second one");
I need the code after the setTimeout to be executed after the code in the setTimeout is executed. Since the code that comes after the setTimeout is not code of my own I can't put it in the function called in the setTimeout...
Is there any way around this?
Is the code contained in a function?
function test() {
setTimeout(...);
// code that you cannot modify?
}
In that case, you could prevent the function from further execution, and then run it again:
function test(flag) {
if(!flag) {
setTimeout(function() {
alert();
test(true);
}, 5000);
return;
}
// code that you cannot modify
}
I came in a situation where I needed a similar functionality last week and it made me think of this post. Basically I think the "Busy Waiting" to which #AndreKR refers, would be a suitable solution in a lot of situations. Below is the code I used to hog up the browser and force a wait condition.
function pause(milliseconds) {
var dt = new Date();
while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}
document.write("first statement");
alert("first statement");
pause(3000);
document.write("<br />3 seconds");
alert("paused for 3 seconds");
Keep in mind that this code acutally holds up your browser.
Hope it helps anyone.
Using ES6 & promises & async you can achieve running things synchronously.
So what is the code doing?
1. Calls setTimeOut 1st inside of demo then put it into the webApi Stack
2. Creates a promise from the sleep function using the setTimeout, then resolves after the timeout has been completed;
3. By then, the first setTimeout will reach its timer and execute from webApi stack.
4. Then following, the remaining alert will show up.
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function demo() {
setTimeout("alert('this alert is timedout and should be the first');", 5000);
await sleep(5000);
alert('this should be the second one');
}
demo();
Just put it inside the callback:
setTimeout(function() {
alert('this alert is timedout and should be the first');
alert('this should be the second one');
}, 5000);
No, as there is no delay function in Javascript, there is no way to do this other than busy waiting (which would lock up the browser).
ES6 (busy waiting)
const delay = (ms) => {
const startPoint = new Date().getTime()
while (new Date().getTime() - startPoint <= ms) {/* wait */}
}
usage:
delay(1000)
You can create a promise and await for its fulfillment
const timeOut = (secs) => new Promise((res) => setTimeout(res, secs * 1000));
await timeOut(1000)
Here's a good way to make synchronous delay in your code:
async function yourFunction() {
//your code
await delay(n);
//your code
}
function delay(n) {
n = n || 2000;
return new Promise(done => {
setTimeout(() => {
done();
}, n);
});
}
Found it here Right way of delaying execution synchronously in JavaScript without using Loops or Timeouts!
setTimeout(function() {
yourCode(); // alert('this alert is timedout and should be the first');
otherCode(); // alert("this should be the second one");
}, 5000);
I think you have to make a promise and then use a .then() so that you can chain your code together. you should look at this article https://developers.google.com/web/fundamentals/primers/promises
You could attempt to replace window.setTimeout with your own function, like so
window.setTimeout = function(func, timeout) {
func();
}
Which may or may not work properly at all. Besides this, your only option would be to change the original code (which you said you couldn't do)
Bear in mind, changing native functions like this is not exactly a very optimal approach.

Categories