避免setTimeout与angular $ watch上的函数重叠

时间:2014-02-17 20:05:24

标签: javascript angularjs

我有这个验证过程,根据第一个函数的返回,淡入或淡出两个div。 setTimeout是为了完成输入,因为它在keyup上监视。系统有效,但问题发生在:

您键入了错误的值(#wrong显示)>你重新输入好的价值>当你输入好的值时,会触发else函数,因为它尚未完成>键入好的值时(.ok显示) #wong显示为并且在setTimeout延迟之后。

有没有办法避免else函数的重叠?也许完全分离真假函数?

function validatePasscode(code) {
    if (array.indexOf(code) > -1) {
        return true;
    }  
}

$scope.$watch('passcode', function(value) {
    var isValid = validatePasscode(value);
    if (isValid) { 
        $scope.loadNewChannel(); 
        $('.ok').fadeIn(200); 
        $('#wrong').fadeOut(200);
    }
    else {
        setTimeout(function(){
            $('.ok').fadeOut(200); 
            $('#wrong').delay(200).fadeIn(200);
        },2000);
    }
});

2 个答案:

答案 0 :(得分:1)

我会采取一些不同的方法。 Angular的想法不是在控制器内部进行DOM操作。您有几个选项 - 一个是在$ scope上公开$ isValid,另一个是创建一个执行动画的指令。

至于限制输入,问题是你在每次按键后任意等待2秒。你真正想要的是等到按键结束 - 即只要有人打字等待,然后一旦他们暂停一段时间重新评估。

你可以使用Underscore或Lo-dash的去抖动来做到这一点。像这样:

var applyValidation = function($scope) {
   $scope.isValid = validatePasscode($scope.passcode);
}

因为debounce在Angular的摘要循环之外触发,你需要$应用它:

var validationDelayed = function($scope) {
    $scope.$apply(function(){applyValidation($scope);});
};

然后你可以观看它,只有在输入结束后才会做出反应。这只会在用户停止输入1秒后触发检查:

var validationThrottled = _.debounce(validationDelayed, 1000);
$scope.$watch('passcode', function(){validationThrottled($scope);});

同样,这将解决超时问题,但我强烈建议将其转换为动画的指令,尽管您可以在此代码中尝试这样:

var applyValidation = function($scope) {
   if(validatePasscode($scope.passcode)) {
      // success animation
   } 
   else {
      // failure animation
   }
}

这是我的一个工作小提琴,它使用了一个类似的概念:http://jsfiddle.net/jeremylikness/5KeMw/(我正在过滤而不是验证,但你可以看到油门是如何工作的)以及一篇关于它的博客文章:http://csharperimage.jeremylikness.com/2013/10/throttling-input-in-angularjs.html

答案 1 :(得分:0)

请始终调用clearTimeout()

var timeoutFunction;
$scope.$watch('passcode', function(value) {
var isValid = validatePasscode(value);
clearTimeout(timeoutFunction);
if (isValid) { 
    $scope.loadNewChannel(); 
    $('.ok').fadeIn(200); 
    $('#wrong').fadeOut(200);
}
else {
    setTimeout(function(){
        $('.ok').fadeOut(200); 
        $('#wrong').delay(200).fadeIn(200);
    },2000);
}

});