admin管理员组

文章数量:1400762

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.

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.

Share Improve this question edited Jun 18, 2013 at 16:51 Sudhir Jonathan 17.5k15 gold badges71 silver badges94 bronze badges asked Jun 18, 2013 at 16:36 KeithRulesKeithRules 2071 gold badge4 silver badges15 bronze badges 15
  • 1 you could try using a global boolean – Peter Berg Commented Jun 18, 2013 at 16:38
  • 2 How is the function still running when user loads another page or reloads the same one? – Dogbert 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. – Paul 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. – Sudhir Jonathan 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. – taz Commented Jun 18, 2013 at 20:52
 |  Show 10 more ments

3 Answers 3

Reset to default 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.

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 */ 
    }
}

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.

本文标签: javascriptCall a function only if it hasn39t been calledrun a function only onceStack Overflow