I'm trying to develop a function that repeats a function x amount of times, just once, not based on settimerinterval or settimeout or anything based on time. I don't want to use a while/for loop directly, I want to use this repeat function.
I've tried something like this:
function repeat(func, times) {
for (x = 0; x < times; x++) {
eval(func)
}
}
But eval doesn't work on a function.
const func = () => console.log("hi");
const times = 3;
Array.from({length: times}, () => func());
I define a function.
I set the number of times to repeat function.
I make an array the size of times to repeat function.
I run the "defined function" on each element of the array.
Just call func and decrement counter and call the function repeat again.
function repeat(func, times) {
func();
times && --times && repeat(func, times);
}
repeat(function () { document.write('Hi<br>'); }, 5);
If Lodash is an option, then _.times
You can also define a reusable function, utilizing setInterval and clearInterval
function runFunctionXTimes(callback, interval, repeatTimes) {
let repeated = 0;
const intervalTask = setInterval(doTask, interval)
function doTask() {
if ( repeated < repeatTimes ) {
callback()
repeated += 1
} else {
clearInterval(intervalTask)
}
}
}
function sayHi() {
console.log("Hi")
}
The following line will run sayHi 5 times without wasting any time between completion of one and the beginning of another.
runFunctionXTimes(sayHi, 0, 5)
It is also possible to pass function arguments to setInerval, you can read more about it here https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval
Using recursion:
function repeat(fn, times) {
var loop = function (times) {
if (times) {
fn(times);
loop(--times);
}
}
loop(times);
}
repeat(function (times) {
console.log(times);
}, 5);
You may not be able to eval() a function, but you can call it. Here's the fix:
function repeat(func, times) {
for (x = 0; x < times; x++) {
func()
}
}
Related
Learning some basic concepts in JavaScript "asynchronicity" from Frontendmasters course JavaScript: The Hard Parts, v2
I am given the exercise (Challenge 5):
Create a function limitedRepeat that console logs "hi for now" every second, but only for 5 seconds. Research how to use clearInterval() if you are not sure how to do this.
And following placeholder was given for this function:
function limitedRepeat() {
//CODE HERE
}
I was able to solve it as following (2 versions):
Version 1
function limitedRepeat() {
var totalLogs = 0;
var logFunc = setInterval(myTimer, 1000)
function myTimer() {
if(totalLogs < 5){
console.log("hi for now");
totalLogs++;
} else {
clearInterval(logFunc);
}
}
}
limitedRepeat(); // should log (every second, for 5 seconds): hi for now
Version 2
function limitedRepeat(totalLogs) {
console.log("hi for now");
var timery = setTimeout(timerable,1000);
function timerable() {
totalLogs++;
if(totalLogs >= 5){
clearTimeout(timery);
} else {
limitedRepeat(totalLogs);
}
}
}
limitedRepeat(0); // should log (every second, for 5 seconds): hi for now
Obviously, I have changed the signature of function in Version 2, so I am curious if there is solution that leverages setTimeout() and clearTimeout() and possibly recursion, that doesn't require signature of function to be changed - in other words for that recursive call set by timeout to somehow memorize how many times was the log printed to console?
With recursion;
function limitedRepeat(count = 0) {
if(count >= 5) return;
console.log('hi')
setTimeout(() => limitedRepeat(++count), 1000)
}
limitedRepeat()
Just make sure you increment before recalling the function.
This is my approach:
var count = 1,
timer = setInterval(limitedRepeat,1000)
function limitedRepeat() {
console.log('Hi for now');
count++;
if(count > 5) clearInterval(timer)
}
Using an inner named IIFE with recursion.
EDIT: We don't even need the closure to memoize the times executed if we pass the parameter to the inner function.
function limitedRepeat() {
const maxTimes = 5;
return (function _limitedRepeat(current) {
console.log("hi for now");
var timery = setTimeout(timerable, 1000);
function timerable() {
current++;
if (current >= maxTimes) {
return
}
_limitedRepeat(current);
}
})(0);
}
limitedRepeat();
I have been working on a piece of code and I was wondering if there is a inbuilt JavaScript method which allows a function to be runned every 4 seconds for seconds and 5 times for example.
Your question is ambiguous in the sense that it is unclear whether you want to call the function five times each interval, or call it with intervals until it has been called five times.
5 times each time interval
You can easily write a higher order function for this:
function multi_repeat(f,dmsec,times) {
function foo() {
setTimeout(foo,dmsec);
for(var i = 0; i < times; i++) {
f();
}
}
setTimeout(foo,dmsec);
}
Now if your function is:
function the_alert() {
alert("Hi");
}
You can run this with:
multi_repeat(the_alert,4000,5);
where 4000 is the number of milliseconds (so 4 seconds is 4000 milliseconds) and 5 the number of times the function should be called.
Stop after 5 calls
In case the procedure should stop after 5 calls, you can define another higher order function:
function repeat_stop(f,dmsec,times) {
var count = 0;
function foo() {
f();
count++;
if(count < times) {
setTimeout(foo,dmsec);
}
}
setTimeout(foo,dmsec);
}
you are looking at the setInverval function.
var counter = 0;
function someFunction(){
console.log('hello world')
}
var interVal = setInterval(function(){
conter++;
if (counter < 5) {
someFunction();
}
else {
clearInterval(interVal );
}
}, 4000);
setInterval will run a function repeatedly with a custom delay between them. To run it five times, you'll have to handle that yourself, e.g.
setInterval(function(){
for (var i = 0; i < 5; i++){
myFunction();
}
},4000);
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval
I want to write a for loop which prints number 1 to 10 with intervals after every iteration "like this"
How can I achieve it? I tried sleep() setInterval() setTimeout(") and what not but can't seem to find any working solution. And if possible I would like to do this using pure Javascript only.
function abc(){
for(i=1;i<=10;i++){
document.write(i+"<br>");
sleep(1000);
}
}
To answer the question, to get something like a sleep function you could just write somehting like this as a helper function
function sleep(dur) {
var d = new Date().getTime() + dur;
while(new Date().getTime() <= d ) {
//Do nothing
}
}
console.log(new Date().getTime())
sleep(1000)
console.log(new Date().getTime())
Then you could call the sleep function after every iteration like
function abc(){
for(i=1;i<=10;i++){
document.write(i+"<br>");
sleep(1000);
}
}
But Note that sleep will freeze your browser in this time and
you don't really wan't this kind of behaviour when you just want to periodiccally do sth
window.setInterval would be what you want in such cases
function abcd(i){
document.write(i + "<br>")
}
function repeatedTimeout(func,times,duration) {
var args = Array.prototype.slice.call(arguments).splice(3);
var i = 0;
args.push(i)
var wrap = function () {
if(args[args.length - 1] >= times)
window.clearInterval(wrap)
else {
func.apply(this,args)
args[args.length - 1]++
}
}
window.setInterval(wrap,duration)
}
repeatedTimeout(abcd,10,1000)
Which would call it 10 times every 1000 milliseconds, whithout freezing the Browers
Heres the JSBin
Update
If it really has to be a for loop, you could do something like this,
regardless of the sense it makes to me
for (var i = 0; i <= 10 ; i++) {
window.setTimeout(
(function (i){
return function() {
document.write(i + "<br>")
}
})(i),i * 1000)
}
In this case heres another JSBin
This would call window.setTimeout in a for loop and a multiple of the timeout with i as the timeout,
this would work, but i'd rather suggest using setInterval like you already did in the Fiddle you posted in the comment
Due to the mostly asynchronous (and single threaded) nature of JavaScript in the browser, constructs such as sleep() aren't the way to go.
You can write a generic function using setTimeout() that will do the looping and then pass in the function that should be run at every interval of x milliseconds. At least you'd have a reusable container in which you can run your code.
function loopn(n, fn, delay)
{
if (n > 0) {
fn();
if (n > 1) {
setTimeout(function() {
loopn(n - 1, fn, delay);
}, delay);
}
}
}
loopn(10, function() {
console.log('hello there');
}, 1000);
You could deconstruct the loop into a recursive function and use setTimeout to implement the pause.
var i = 0;
var limit = 10;
function loop(){
console.log(i);
i++;
if(i < limit)
{
setTimeout(loop, 100);
}
}
loop();
I'm new to javascript and am trying to call a function using setTimeout from within a for loop. The loop executes for each member of a nodeList.
I'm finding that the function I'm calling with setTimeout is only actually executing during the last iteration of the loop. In the example below, I would like to make three separate calls to setTimeout but I'm finding that the first two calls are ignored.
function moveants(e, stepdistance) {
. . . . .
for(var i = 0; i < 3; i++)
{
var nextAnt = antgroup.childNodes[i]
nextAnt.count = 0;
nextAnt.member = i;
setTimeout(function () { takeStep(nextAnt, mouseclickX, mouseclickY, 10) }, 0);
}
}
function takeStep(ant, destX, destY, stepDistance) {
. . . .
. . . .
if( condition )
{
return;
}
else
{
takeStep(ant, destX, destY, stepDistance);
}
}
I have seen other posts that describe making multiple calls to setTimeout. Amazingly (to me), the multiple calls will work if I simply take them out of the for loop like this.
setTimeout(function () { takeStep(antgroup.childNodes[0],
mouseclickX, mouseclickY, 10) }, 10);
setTimeout(function () { takeStep(antgroup.childNodes[1],
mouseclickX, mouseclickY, 10) }, 10);
setTimeout(function () { takeStep(antgroup.childNodes[2],
mouseclickX, mouseclickY, 10) }, 10);
I just can't figure out why there is a difference between calling them from within a for loop and calling them outside of one.
I am getting valid return values from the setInterval call in every case.. it's just that with only the last iteration of the for loop does the function actually execute.
Thanks in advance for any help.
nextAnt will be overwritten on every loop, so takeStep() will be called 3 times, but always with the same arguments.
You may try this instead:
(function(a,b,c){
setTimeout(function(){
takeStep(a,b,c,10)}, 0);
})(nextAnt, mouseclickX, mouseclickY);
If your not setting a delay, then why bother with setTimeout?
In the loop your delay is set to 0, outside the loop you've used 10. Also, outside the loop you've assigned values to count and member, but not outside the loop?
Try this:
function moveants(e, stepdistance)
{
for (var i = 0; i < 3; i++)
{
setTimeout("takeStep(antgroup.childNodes[i], mouseclickX, mouseclickY, 10)", 0);
}
}
or this:
function moveants(e, stepdistance)
{
for (var i = 0; i < 3; i++)
{
takeStep(antgroup.childNodes[i], mouseclickX, mouseclickY, 10);
}
}
I would like to create a pause inside a while loop so that I can create n animations that each appear 3 seconds after the other.
I've tried the following, but it doesn't work. Would love to have someone show me what I'm doing wrong.
i=0;
while (i < n) {
someanimation();
setTimeout(function(){
i++;
}, 3000);
};
setTimeout does not pause; it asks Javascript to run some other code later.
Googling for "setTimeout loop" tells you exactly what you need to know. If you look around a little bit, it even mentions setInterval. The difference: using setTimeout to loop will wait 3 seconds in between loops, whereas setInterval will make it take 3 seconds total for the loop (including however much time the animation takes, as long as it's less than 3 seconds :) ). Also, setInterval constructs an infinite loop that you'll have to break out of after the desired number of times; setTimeout requires you to construct the loop yourself.
i = 0;
// setTimeout approach
function animation_loop() {
someAnimation();
setTimeout(function() {
i++;
if (i < n) {
animation_loop();
}
}, 3000);
};
animation_loop();
// setInterval approach
i = 0;
someAnimation();
iid = setInterval(function() {
i++;
if (i < n) {
someAnimation();
} else {
clearInterval(iid);
}
}, 3000);
setTimeout is a little trickier than that because it doesn't block (i.e. it doesn't finish waiting on the timeout before continuing with the program).
What you want is closer to this:
var i = 0;
function nextFrame() {
if(i < n) {
someanimation();
i++;
// Continue the loop in 3s
setTimeout(nextFrame, 3000);
}
}
// Start the loop
setTimeout(nextFrame, 0);
It may also be worth your while to read up on setInterval as a possible alternative.
Well, thanks to ES6-7 with Promises we can now make a pause and make it look nice at the same time!
var id = 0;
async function do() {
while(true) {
await pause(id);
//will happen only after pause is done
id++;
}
}
function pause(id) {
return new Promise(resolve => setTimeout(() => {
console.log(`pause ${id} is over`);
resolve();
}, 1500));
}
do();
One of the way of doing it is to use RxJS. Please take a look at working example here
Rx.Observable
.interval(1000)
.take(10)
.subscribe((x) => console.log(x))
create a function like:
function sleep_until (seconds) {
var max_sec = new Date().getTime();
while (new Date() < max_sec + seconds * 1000) {}
return true;
}
and then change your code to
i=0;
while (i < n) {
someanimation();
sleep_until(3);
do_someotheranimation();
};
You are not very specific about what you want to do, but I'd say the main problem is that you call someanimation() without a delay. So maybe this solves it for you:
for (var i = 0; i < n; i++) {
setTimeout(someanimation, 3000 * i);
};
Note the missing () after someanimation as it is the callback for setTimeout().
function myFunction() {
var x;
for(var i=0;i<10;i++){
if (confirm("Press a button!") == true) {
x = "You pressed OK!";
} else {
x = "You pressed Cancel!";
}
document.getElementById("demo").innerHTML = x;
}
}``