在上一个事件完成之前使用新数据处理事件

时间:2012-05-11 19:57:49

标签: javascript jquery

此代码有两个输入:div,div(实际上是文本框)和target(数字)。然后它将以伪动画的方式尝试输入/减少数字。问题是我使用jQuery滑块作为一种输入形式,在第一次调用完成之前可能会导致多次调用。这不是问题,除非滑块快速增加,然后在增加rollUp完成之前减小,导致永久递减div。我无法弄清楚是什么导致了它。想法?

function rollNum(div, target) {
var contentString = $(div).val();
content = parseInt(contentString.substring(1));
if(content === target)
    return;
else if(div !== "#costMinusMSP" && div !== "#savingsWithMSP") {
    var total = rollNumTotalCost(div, target);
    rollNum("#costMinusMSP", total);
    rollNum("#savingsWithMSP", total /*- somehow find the cost here*/)
}
if(isNaN(content))
    content = 0;
var remainingChange = target - content;
if(remainingChange > 0)
    loopUp();
else
    loopDown();
function loopUp() {
    var length = remainingChange.toString().length;
    var incrementBy = 1;
    //Find how far away we are from target
    for(var i=0;i<length-1;i++)
        incrementBy *= 10;
    content += incrementBy;
    remainingChange -= incrementBy;
    $(div).val("$" + (content))
    if(content === target)
        return;
    else if(content > target) {
        $(div).val("$" + (target));
        return;
    }
    setTimeout(loopUp, 60);
}
function loopDown() {
    remainingChange = Math.abs(remainingChange);
    var length = remainingChange.toString().length;
    var decrementBy = 1;
    //Find how far away we are from target
    for(var i=0;i<length-1;i++)
        decrementBy *= 10;
    content -= decrementBy;
    remainingChange -= decrementBy;
    if(content < target) {
        $(div).val("$" + (target));
        return;
    }
    //This ensures we won't promise our clients negative values.
    if(content <= 0) {
        $(div).val("$0");
        return;
    }
    $(div).val("$" + (content))
    if(content === target)
        return;
    setTimeout(loopDown, 60);
}
}

奇怪的是,调整另一个滑块(修改一个不相关的div)可以修复永久的减量。

我尝试过的事情: - 创建函数设置为true的布尔“运行”,然后在返回之前返回false。如果运行是真的,那么函数将等到它为假以继续执行。这会杀死浏览器或达到最大堆栈。

1 个答案:

答案 0 :(得分:41)

多年前的几个肯定:自从你提出这个问题以来,你已经学到了很多东西,尤其是关于管理州和国家的问题。多个事件(更不用说如何正确地询问StackOverflow问题)。一个简单的答案是这样的:

var rolling = false;

function rollNum(div, target) {
  if (rolling) { return; }
  rolling = true;

  // Set rolling to false when done
}

这一切都很好但是它忽略了我们在滚动时发生的任何事件。以上不会调整第一次调整后滑块的变化,但是在数字完成滚动之前。现在,我(我们?)会使用Angular($scope.$watch会在这里派上用场)但是当你正在研究它时它并不存在。为什么我们不检查滑块上的 live 值,而不是传递目标数字? (注意使用vanilla JS,它的很多更快)。

var rollNum = function(textarea) {
  var content = parseInt(textarea.value.substring(1), 10)
    , target = parseInt(document.getElementById('sliderId').value, 10);

  if (content === target) {
    return;
  }

  // Roll up/down logic

  setTimeout(function() { rollNum(textarea); }, 60);
};

其他一些misc更改:

  • if语句后使用括号。 Waaaay更容易调试
  • 忘记parseInt
  • 中的基数参数

不幸的是,你没有想过要包含一个JSFiddle,所以我不能提供现场演示。