3

I have a function animate_images running on some of my website's pages that performs a certain animation.

The problem I'm experiencing is that when a user navigates to the same page again, the function is called for the second time, in addition to its already running instance.

Is there a way to do something like this:

if ! (animate_images) {
  animate_images();
}

Essentially, I want to make sure that animate_images never runs more than once, no matter how many times it is actually called.

15
  • 1
    you could try using a global boolean Commented Jun 18, 2013 at 16:38
  • 2
    How is the function still running when user loads another page or reloads the same one? Commented Jun 18, 2013 at 16:39
  • 2
    You could add to animate_images an is_running property, set it true at the start of the animate_images() function and then set to to false whenever the interval / timeout is cleared / the animation is stopped. Commented Jun 18, 2013 at 16:43
  • 1
    I like Paulpro's idea, but whatever you do, please do not use a global boolean. Once you start down that road you'll have your entire app running on global state sooner than you know it. Commented Jun 18, 2013 at 16:49
  • 1
    Yes, if you know that the function will never be instantiated more than once (not called with new), then you can use a "static" property of your function object, as in animate_images.is_running. I can't remember offhand - that might technically make animate_images.is_running a global (or in the same scope as is_running), as opposed to actually being a property of is_running, but the effect should be the same. If you were instantiating animate_images with new, then you would use this. IIRC in Javascript this is scoped to the "closest" function instance. Commented Jun 18, 2013 at 20:52

3 Answers 3

4

Take a look at the once function from underscore.js - linked here.

Essentially, you wrap the function in another one that has a flag variable inside it. Call the function if the flag is unset and set the flag when you call it.

_.once = function(func) {
  var ran = false, memo;
  return function() {
    if (ran) return memo;
    ran = true;
    memo = func.apply(this, arguments);
    func = null;
    return memo;
};

};

If you don't want to add underscore to your website (I think that's the first thing you should do when starting any website, but I digress), do this:

runOnlyOnce = function(func) {...} // As defined above

animate_images = runOnlyOnce(animate_images);

or

animate_images = runOnlyOnce(function(){
    alert('Animate all the things!');
});

The function itself has no dependencies on the rest of underscore.

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

8 Comments

Thank you, @Sudhir – is there a way to do that without adding an additional JS library to my already library- heavy website?
Yes, just rewrite this function and give it a name you like
Could you please add the placeholder for my function inside the one you posted, @SudhirJonathan? I'm pretty new to JavaScript and even that is a bit of a challenge. Should it be after the return memo?
Or maybe I misunderstood you and all I need to wrap the function is to place it inside the parentheses, when runOnlyOnce function is called, as you showed?
Yes, you can also do this: animate_images = runOnlyOnce(function(){alert('Images Animated');});
|
2

Use a static property of your function object, as in a boolean animate_images.isRunning. At the start of animate_images, encapsulate the animation initialization with something like

animate_images() {
    // on first load, animate_images.isRunning is undefined,
    //     so (!animate_images.isRunning) returns true.
    if(!animate_images.isRunning) { 
        /* launch animation */;
        // define animate_images.isRunning and assign true
        animate_images.isRunning = true;
    } else { 
        /* animation already initialized */ 
    }
}

Comments

2

You could override your function with an empty function once it has been executed:

function a(){
    console.log("hello");
    a = function(){};
}

a();  //"hello"
a();  //>>nothing happens<<

Actually this will just override the reference a to your function. So this only works if you don't reference to the same function multiple times. If you do something like this:

function a(){
    console.log("hello");
    a = function(){};
}

var obj { b:a };

a();  //"hello"
a();  //>>nothing happens<<
obj.b(); //"hello"

this method will fail.

Comments

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.