2

How to use jquery to create infinite animation, BUT NOT using recursion way?

The recursion solution I found: jQuery .animate() callback infinite loop

The problem of using recursion is: while animating, the browser tab of currrent page will take MORE and MORE memory.

8
  • 2
    did you actually verify that it takes up more and more memory Commented Mar 7, 2015 at 13:30
  • 1
    Please show the code you are using. Commented Mar 7, 2015 at 13:31
  • 2
    Why not using CSS animation? Commented Mar 7, 2015 at 13:33
  • @Foon I opened my page in chrome an using chrome task manager to check it (shift + esc), the memory of that page keep increasing per sec. Commented Mar 7, 2015 at 13:53
  • @charlietfl I was using the same pattern following: stackoverflow.com/questions/6461945/… Commented Mar 7, 2015 at 13:55

2 Answers 2

3

You have actually made a mistake in assuming that the code is "recursive". It is not recursive. Your comment that "the browser tab of current page will take MORE and MORE memory." is not because of any recursion in that code. If you have a memory leak per second (as per your comments), then the problem lays elsewhere.

The instances of the code actually run sequentially and not via nested stack calls (i.e. linear and not recursive).

Using the most basic example you linked to:

function start() {
    $('#element').animate({}, 5000, 'linear', start);
}
start();

here is what actually happens:

  • A function called start is defined and then called once
  • Inside start, an animation operation is started, then start immediately exits!
  • The animate just adds information to a single animation queue for the element, then returns.
  • The animation queue is processed step by step by a separate process (single timer etc).
  • When the queued entry has met its expected end state, it calls the callback - The global start function stored in the queued entry.
  • That simple adds another entry on the animation queue and exits.

Basically the code looks recursive, but as the operations are async, via a queue, it is not recursive. I don't know if there is an official name for these, so I just call them chained callbacks.

Sign up to request clarification or add additional context in comments.

10 Comments

I've heard the term "pseudo-recursion" for it. Basically, it is recursion, but a call-stack optimised one (like tail calls).
@Bergi: Call me old-school, but that does not meet my definition of recursion (code actually calling itself). In this instance a separate process is working through the queue.
Oh, I'm coming from a functional programming background, where you don't care about "calls" at all and more about structure. It definitely is a recursive approach :-)
@Bergi: Fair enough. His question implied concerns about "growing memory usage", which implied stack-based recursion, rather than the problem being recursive in nature, hence my answer.
@TrueBlueAussie regardless of what theories you have, the code you provide here causes the memory usage to quickly increase for that tab. My solution above is a little better, but still eats memory.
|
0

UPDATED WITH TEST RESULTS

Conclusion... All methods burn up the same amount of memory and it eventually gets released, doesn't keep building forever so not really an issue.

Example 1

This is the code the OP originally had a problem with memory usage increasing in Chrome.

(function($){
    $(function(){  //document.ready

        function start() {
                $('#animate').animate({'margin-left':'150px'}, 1000, function () {
                    $(this).animate({'margin-left':'50px'}, 1000, 'linear', start);                
                });
        }
        start();

    });
})(jQuery);

Example 2

Current solution including a callback as requested by Bergi to avoid potential "drifting" in setinterval.

(function($){

    $(function(){  //document.ready

    });

    (function customSwipe(element) {
        element
            .animate({"margin-left" : "150px"}, 1000)
            .animate({"margin-left" : "50px"}, 1000, function(){
                setTimeout(function(){
                    customSwipe(element);
                }, 2000);
            });
    })($('#animate'));

})(jQuery);

Example 3

Original Answer I gave, using setInterval()

(function($){
    $(function(){  //document.ready

            setInterval(function(){
                    $("#animate").animate({'margin-left':'150px'},1000);
                    $("#animate").animate({'margin-left':'50px'},1000);
            },2000); 

    });
})(jQuery);

Skeleton w/ Jquery

Empty page w/ only the #animate element

(function($){
    $(function(){  //document.ready



    });
})(jQuery);

DATA AFTER TAB OPEN FOR 10 MINUTES

CODE            STARTING    ENDED
Example 1       14.300k     19.996k
Example 2       14.300k     20.020k
Example 3       14.300k     20.344k
Skeleton w/ jQuery  14.300k     15.868k

Interesting that the code that did nothing still increased usage slightly. These values go up and down as memory is used and released. Another thing would be to use the "purge memory" button in task manager to see how much of that used memory is garbage waiting to be collected.

DATA AFTER 25 MINUTES

Example 1       14.300k     18.640k
Example 2       14.300k     18.724k
Example 3       14.300k     18.876k
Skeleton w/ jQuery  14.300k     15.868k

Conclusion... All methods burn up the same amount of memory and it eventually gets released, doesn't keep building forever so not really an issue.

So just using the most solid, sound code would be the best option, Example 2 would be my choice.

UPDATED USING CALLBACK

Have you tried using setTimeout with $.animate()?

(function($){
    (function customSwipe(element) {
        element
            .animate({'margin-left':'150px'}, 1000)
            .animate({'margin-left':'50px'}, 1000, function(){
                setTimeout(function(){
                    customSwipe(element);
                }, 2000);
            });
    })($('#animate'));

    $(function(){  //document.ready


    });

})(jQuery);

Remove the setTimeout() if you don't need it to delay between animations.

JSFIDDLE of the above code working...

You might also want to look into this for more intricate animations.

http://api.jquery.com/jquery.fx.interval/

Conclusion... All methods burn up the same amount of memory and it eventually gets released, doesn't keep building forever so not really an issue.

What you are seeing in the Chrome TM is every time it fires the animation, that much memory is requested and the OS "commits" that memory to chrome for the operation. Once the operation is completed, the memory is still committed. At some point Chromes garbage collector comes along and releases that memory and your usage stats will drop back down. So you will see the memory going up and down if you watch it long enough.

You can put --purge-memory-button at the end of your Chrome command line to have a Purge Memory button available in Chrome TM. This might help you to see how much memory is actually waiting to be released.

Hope this answer helps you and maybe some others.

9 Comments

this is not really a useful answer. setInterval may drift, and when it does get a bit faster than the actual animation you really start filling up memory. To know when the animation has finished, use callbacks, that's what they are for.
@bergi do I really deserve a downvote for that? I didn't get an upvote from the OP in the first place. Plus OP marked it correct. Meaning it worked for them, so the "Possibility" of drifting, which is remote, doesn't affect his implementation. Please remove downvote. Thanks.
If you went around downvoting everyone who had a solution with an obscure possiblity of some rare failure happening, then you'd be downvoting all day, but hey, maybe that's what you do. I personally have better things to do than hate on people trying to help others.
Yes, I think it deserves a downvote because I consider it a bad practise (And it's not only drifting, but also readability and maintainability, what if someone changes 1000 to 1500 but misses to adjust 2000?). It doesn't matter whether OP upvoted or not, or whether he accepted it. I'm not hating around, and my votes are not personal. It's just when I come across a good answer, I upvote it, and when I come across a bad answer I downvote and comment what is wrong/could be improved from my pov.
@Littlee I updated this answer with a better solution.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.