如果它被多次调用,如何停止相同函数的先前实例?

时间:2015-03-08 21:24:52

标签: javascript function multiple-instances

我写了一个自定义动画功能。它通常工作正常,但是当我使用不同的endCallbacks快速连续调用animate();时,有时回调非常严重,导致在错误的时间执行错误操作。

问题是函数多次实例化并执行直到达到endValue。 currentValue变化得太快,我只能看到我的html页面动画中的最后一个值。这隐藏了这种不受欢迎的行为。

第二次拨打animate();时我需要的是结束animate();的第一个实例并触发一个带有新值和新回调的新实例。同时我想停止setTimeout()函数,以确保没有触发错误的回调。

window.onload = function(){
    document.addEventListener('click', // some button
        function (){
            animate(1, 10);
        }, false
    );
}

function animate(startValue, endValue, callback, endCallback) {
    var startValue = startValue,
        currentValue = startValue,
        endValue = endValue,
        callback = callback,
        timeout = null;

    loopAnimation();
    function loopAnimation(){
        if (currentValue != endValue){
            timeout = setTimeout(function(){
                currentValue++;

                // Callback executes some page manipulation code
                if (typeof callback !== "undefined") callback(currentValue); 
                console.log(currentValue);
                loopAnimation();
            },500)
        } else {
            console.log("This callback triggers some specific changes in my page");
            if (typeof endCallback !== "undefined") endCallback();
        }
    }
}

而不是在控制台中看到: 1,2,3, - 1,4,2,5 ...... 6,9,7,10,8,9,10

我想看到: 1,2,3, - 1,2 ...... 7,8,9,10

但是,请记住,由于我在脚本中使用animate()的方式,我不能依赖于知道输入变量的名称或范围。这使我无法自己解决它。

2 个答案:

答案 0 :(得分:1)

虽然这不是你要求的实现,但我想知道Underscore的油门或去抖是否能满足需求?

debounce将确保您的函数每秒调用次数不超过X次 - 每次调用时仍会执行一次,但后续调用将延迟以满足您的速率限制。因此,如果你快速连续两次调用动画,debounce可以延迟第二次执行,直到第一次执行或者你有什么。

throttle基本上会忽略速率限制期间发生的呼叫。因此,如果你在100毫秒内调用你的动画10次,你可以把它扔掉,除了第一个。 (实际上,它会执行第一个,在等待期结束时加一个)。

您不需要使用所有下划线来获取这些方法;我见过人们经常从下划线复制和粘贴去抖动和/或油门功能。如果你谷歌,你可以找到一些独立的节流或去抖实现。

节流和去抖通常用于你的情况,动画。

对于你的原始规范,实际上“结束animate()的第一个实例” - 在javascript中没有很好的可靠方法。没有真正的通用方法来“取消”已经执行的功能。如果你可以使用debounce或油门工作,我认为这将减少挫败感。

答案 1 :(得分:0)

您需要的是存储您使用的最后一个超时ID。因此,下次开始新动画时,使用此超时ID和clearTimeout清除正在进行的动画 我发现在函数本身上存储间隔很方便。

在这里查看jsbin:  http://jsbin.com/nadawezete/1/edit?js,console,output

window.onload = function(){
    document.addEventListener('click', // some button
        function (){
            animate(1, 10);
        }, false
    );
};

function animate(startValue, endValue, callback, endCallback) {   
    var currentValue = startValue;
    if (animate.timeout) clearTimeout(animate.timeout);
    loopAnimation();
    function loopAnimation(){
        if (currentValue != endValue){
            animate.timeout = setTimeout(function(){
                console.log(currentValue);
                currentValue++;    
                // Callback executes some page manipulation code
                if (callback ) callback(currentValue); 
                loopAnimation();
            },500);
        } else {
            console.log("This callback triggers some specific changes in my page");
            if (endCallback) endCallback();
        }
    }
}