calling function in a loop in javascript
Asked Answered
I

5

6

I am trying to call a function from within a loop in a way that when the function finishes executing, the loop continues to the next iteration and calls it again. But instead the loop doesn't wait for the function to finish and instead calls 4 instances of the function and runs them at the same time! Should I put the whole function in the loop or is there to make the loop wait for the function to be executed? Thanks

    for (var i=2; i<=4; i++){
        galleryAnimation(i); //This is executed 3 times at once
    }
    function galleryAnimation(i){
        $("#pic" + i).delay(delayTime).fadeIn(duration);
    }       
Inconsiderate answered 19/8, 2013 at 10:52 Comment(0)
C
1

Simplistic solution: Increase the timeout by a factor every time.

var i, factor, 
    duration = 250,
    delayTime = 500;

for (i = 2, factor = 0; i <= 4; i++, factor++) {
    galleryAnimation(i, factor);
}

function galleryAnimation(i, factor) {
    $("#pic" + i).delay(factor * delayTime).fadeIn(duration);
}

This runs the same way your approach does, only the delays get longer every time.

Generic solution 1 - work with setInterval() to have your worker function (the one that does the fadeIn) called in predefined intervals:

var elements = $("#pic2,#pic3,#pic4").toArray(),   // or any other way to select your elements
    duration = 250,
    delayTime = 500,
    intervalId = setInterval(function () {
        $(elements.shift()).fadeIn(duration);
        if (elements.length === 0) {
            clearInterval(intervalId);
        }
    }, delayTime);

Generic solution 2 - work with callbacks that are called when the previous animation finishes:

var elements = $("#pic2,#pic3,#pic4").toArray(),   // or any other way to select your elements
    duration = 250,
    delayTime = 500,
    next = function () {
        $(elements.shift()).delay(delayTime).fadeIn(duration, next);
    };

next();  // start the chain
Convergent answered 19/8, 2013 at 11:41 Comment(0)
C
3

The function is being executed 3 times just like you requested, the problem is that both delay and fadeIn use timers: they set a timer in the future when the function will be executed and return immediately: they are non-blocking calls. So, in your case, because you're calling the function 3 times at, let's say, 0.0001s, 0.0002s, and 0.0003s, the three kick in at, let's say, 5.0001, 5.0002 and 5.0003.

What you had in mind were blocking calls to these functions. You expected the whole execution to stop until the animations were finished. This would stop the whole browser Javascript engine for the duration, meaning no other animation or user javascript interaction would be possible.

To solve it, you have to use callbacks. You can supply a function to fadeIn that will be called once the animation has completed:

http://api.jquery.com/fadeIn/

You can use queues to simulate the same on delay():

Callback to .delay()

Cell answered 19/8, 2013 at 10:58 Comment(4)
Seems like what I've been trying to do is very wrong and won't work like I expected. I used callbacks before, but I have to write code for each photo and it gets really nested and hard to add more in the future! Isn't there another way?Inconsiderate
Noone said asynchronous programming was easy! :) You don't need to write code for each photo, you can just write a normal function that takes parameters and use a callback with parameters!Cell
could you please show me an example? I can't seem to understand your suggestion. I know how to use callbacks, but there must be code in a callback function and the loop would still run anyway. I'm just going to have 3 callbacks running at the same timeInconsiderate
Of course, you don't want to use a loop here. The callback to the first animation should be a function that triggers the second animation, and so on.Cell
C
1

Simplistic solution: Increase the timeout by a factor every time.

var i, factor, 
    duration = 250,
    delayTime = 500;

for (i = 2, factor = 0; i <= 4; i++, factor++) {
    galleryAnimation(i, factor);
}

function galleryAnimation(i, factor) {
    $("#pic" + i).delay(factor * delayTime).fadeIn(duration);
}

This runs the same way your approach does, only the delays get longer every time.

Generic solution 1 - work with setInterval() to have your worker function (the one that does the fadeIn) called in predefined intervals:

var elements = $("#pic2,#pic3,#pic4").toArray(),   // or any other way to select your elements
    duration = 250,
    delayTime = 500,
    intervalId = setInterval(function () {
        $(elements.shift()).fadeIn(duration);
        if (elements.length === 0) {
            clearInterval(intervalId);
        }
    }, delayTime);

Generic solution 2 - work with callbacks that are called when the previous animation finishes:

var elements = $("#pic2,#pic3,#pic4").toArray(),   // or any other way to select your elements
    duration = 250,
    delayTime = 500,
    next = function () {
        $(elements.shift()).delay(delayTime).fadeIn(duration, next);
    };

next();  // start the chain
Convergent answered 19/8, 2013 at 11:41 Comment(0)
S
0

one thing you can do, is to use an identifier (boolean) and then, in the loop, you test the identifier to decide if the loop can continue or stop. For example, function galleryAnimation(i, iBool){ $("#pic" + i).delay(delayTime).fadeIn(duration);
iBool = 0; }

Then on the return;

for (var i=2; i<=4; i++){
    galleryAnimation(i, iBool); 
    // If iBool = 0 then continue
    // Else Break
}

that might be a solution, as the loop will need the returning value to determine the next step, to continue or break.

Semivowel answered 19/8, 2013 at 11:0 Comment(0)
I
0

I came with my own solution that seemed to work perfectly, this is my code:

function fadeInAnimation(index){
        $("#pic" + index).delay(delayTime).fadeIn(duration, function(){
            photoIndex();
        });
    }

    function photoIndex(){
        index++;
        fadeInAnimation(index);
    }
    fadeInAnimation(index);
});

I have realized that using loops is a really bad idea with things like this. This code will allow me to add as many images as I want just by renaming them in the folder rather than coding them in manually as callbacks for each photo. Thanks for those who answered. Your suggestions are great and will definitely remember them in other applications like this one

Inconsiderate answered 19/8, 2013 at 13:34 Comment(0)
C
0

Anyone know can use function like that in For loops:

function plus(x){
    return x + 1
}



let number;
let sum = 0;
for (let count = 1; count <= 3; plus(count)) {
    number = Number(prompt("enter the number: " , 1));
    sum += number;
}
console.log(sum);
Calumniate answered 4/3 at 18:34 Comment(1)
Hello there! Thanks for contributing to StackOverflow. Your response could benefit from a bit more detail to provide a clearer understanding for readers. Consider adding some evidence or examples to support your solution. Feel free to edit your answer to enhance its credibility. Additionally, your code block leaves the user's browser in an infitnite loop, I'd suggest incrementing count so that StackOverflow users don't have the reload the webpage after each run of your snippet.Lignocellulose

© 2022 - 2024 — McMap. All rights reserved.