繁体   English   中英

即使在jQuery中不满足条件,也要执行else语句

[英]Having my else statement executed even if condition isn't met in jQuery

好吧,我的标题不可能是真的,因为编程语言不会犯这样的错误,但是这种情况正在发生。 因此,我们可以肯定地说我的逻辑存在问题。

我有一段jQuery / JS代码,就像在AJAX调用之前在SO的注释部分中检查这里要去的字符数一样。 因此,代码被认为是这样的:

如果输入的字符数少于N,则将N个字符减计数(例如,要走2个字符,要走1个字符...)
否则进行AJAX调用,并在成功时显示结果。

当您第一次进入表单时,此过程很顺利:

  • 你得到的是空字段
  • 开始输入
  • 字符指示器不断减少
  • 我们点击了“断点”,它停止检查
  • 进行AJAX呼叫
  • 我们会在成功回调中显示一条消息

但是,当我继续使用退格键删除字符(或删除)并再次进入断点(必须看到“ N走”)时,我再次显示了“ N走”部分,但是AJAX调用通过了即使包裹在else也是else 这很奇怪。 结果看起来像这样:

AJAX失败

红色文本是AJAX成功回调,黄色部分是字符计数器。

这是我的jQuery:

var delay = (function(){
    var timer = 0;
        return function(callback, ms){
            clearTimeout (timer);
            timer = setTimeout(callback, ms);
        };
})();

$('#reg_email').keyup(function(){

    var min_password_chars = 6;
    var email_input = $('#reg_email').val();
    var email_prev  = '';

    if (email_input.length < min_password_chars)
    {
        $('.email-check').text('');

        if ($('.email-check').children('.yellowish').length == 0)
        {
            $('.email-check').append('<span class="yellowish"><span class="counter">6</span> to go</span>');
        }

        $('.email-check .counter').text(min_password_chars - email_input.length);
    }
    else
    {
        delay(function(){
            $.ajax({
                type: 'GET',
                url: 'ajax.php?action=check_email',
                data: { email: JSON.stringify(email_input) },
                success: function(data){
                    var response = $.parseJSON(data);                           
                    $('.email-check').append(response.message);

                    email_prev += response.sent_email;
                }
            });
        }, 1500);

        if (email_input != email_prev)
        {
            $('.email-check').text('');
        }
    }
});

这是HTML:

<div class="form-group">
    <label for="rep_email">Repeat email</label>
    <input type="email" class="form-control" id="rep_email" name="email_rep" placeholder="Enter your email" required>
    <p class="email-check pull-right validate-note"><span class="yellowish"><span class="counter">6</span> to go</span></p>
</div>

我可能做错了什么? 我的逻辑在哪里使我失望?

您的ajax调用是双重异步的,因此这可能会使调试和结果感到困惑。 这种类型的东西实际上很难用断点调试。 我发现我经常不得不在代码中放入console.log()语句,这样我才能实时查看事件的实际顺序。

else子句的执行部分在第一次遇到else子句之后的某个时间执行,并且由于您的delay()和AJAX调用的异步特性而被双重延迟。 如果您不针对特定情况进行编码,则这将导致调试困难,并且很容易导致编程错误。

首先,它们是异步的,因为您使用的是delay() ,我假设它是setTimeout() 这意味着您甚至要到某个时候才开始进行Ajax调用。 其次,它们是异步的,因为它们是异步ajax调用。 因此,他们在else分支执行之后的某个时间调用成功处理程序。 实际上,您可以在其他字符完成执行之前先键入它们。

您还会遇到关闭问题,即您可能在成功处理程序中使用的数据与最初发送ajax调用时的数据不同(因为自声明ajax调用以来它已更改)。


在下面的代码中,我应用了这些修复程序:

  1. 取消任何以前未触发的计时器,这样当您键入更多字符时,您就不会再使用计时器了。 这将防止您在计划另一个Ajax调用时发送它。
  2. 始终将最新值发送到服务器,即使自初始设置计时器以来已对其进行了修改。
  3. 如果自设置此计时器以来已对其进行了修改,但是现在它太短了,请不要将其发送给服务器,因为已经报告了太短的错误。

这样做并不是在计划下一个ajax调用时取消任何正在进行的ajax调用,但这只是服务器效率问题,而不是正确性问题。 您的代码还假定将同时处理多个在飞行中的ajax调用,并按顺序返回。 在现实世界中通常是这种情况,但如果不进行编码以明确排序,就无法保证。

var emailTimeout;
$('#reg_email').keyup(function(){
    var min_password_chars = 6;
    var email_input = $('#reg_email').val();
    var email_prev  = '';

    if (email_input.length < min_password_chars)
    {
        $('.email-check').text('');

        if ($('.email-check').children('.yellowish').length == 0)
        {
            $('.email-check').append('<span class="yellowish"><span class="counter">6</span> to go</span>');
        }

        $('.email-check .counter').text(min_password_chars - email_input.length);
    }
    else
    {
        clearTimeout(emailTimeout);
        emailTimeout = setTimeout(function(){
            // get latest email value, might have changed
            var latest_email_input = $('#reg_email').val();
            // if it's not long enough, don't send to the server
            if (latest_email_input.length < min_password_chars) return;

            $.ajax({
                type: 'GET',
                url: 'ajax.php?action=check_email',
                // always retrieve latest value of data (may have changed)
                data: { email: JSON.stringify(latest_email_input) },   
                success: function(data){
                    var response = $.parseJSON(data);                           
                    $('.email-check').append(response.message);

                    email_prev += response.sent_email;
                }
            });
        }, 1500);

        if (email_input != email_prev)
        {
            $('.email-check').text('');
        }
    }
});

仅供参考,这是您的酷炫延迟功能的更通用的版本,只需传递用于不同用途的不同标记字符串,即可同时用于多种不同用途:

var delay = (function(){
    var timers = {};
        return function(tag, callback, ms){
            clearTimeout(timers[tag]);
            timers[tag] = setTimeout(function() {
                delete timers[tag];
                callback();
            }, ms);
        };
})();

// sample usage
delay("emailKey", fn, 1500);
delay("search", fn, 500);

它看起来像一个竞争条件,由$.ajaxdelay()复合。 在事件循环的下一个滴答之前,您的ajax调用不会触发,因此退出if块后,将附加您的ajax返回的消息。

我将执行以下操作:

  1. 消除事件处理程序的抖动(仅在给定时间范围内的最后一个事件时才调用事件处理程序)。 尝试使用underscore.js的debounce ,对于这种情况非常有用
  2. 将帮助程序文本清除功能移到事件处理程序的顶部(不需要重复该代码)

这是我将其重写的方式:

$('#reg_email').keyup(_.debounce(function() {

    $('.email-check').text('');

    var min_password_chars = 6;
    var email_input = $('#reg_email').val();
    var email_prev  = '';

    if (email_input.length < min_password_chars) {
        if ($('.email-check').children('.yellowish').length == 0) {
            $('.email-check').append('<span class="yellowish"><span class="counter">6</span> to go</span>');
        }

        $('.email-check .counter').text(min_password_chars - email_input.length);
    } else {
        $.ajax({
            type: 'GET',
            url: 'ajax.php?action=check_email',
            data: { email: JSON.stringify(email_input) },
            success: function(data){
                var response = $.parseJSON(data);                           
                $('.email-check').append(response.message);

                email_prev += response.sent_email;
            }
        });
    }  
}), 1500);  

假设您在email字段中输入abcdefgh ,然后在其上退格,这将导致5个ajax调用,由于delay ,它们至少分散了5 * 1.5 = 7.5秒。

要计算这一点,请从abcde开始:

  • abcde尚未。
  • abcdef -ajax调用1
  • abcdefg -Ajax通话2
  • abcdefgh -Ajax通话3
  • abcdefg -ajax调用4
  • abcdef -ajax调用5

编辑字段后,ajax调用将继续,两次调用之间至少间隔1.5秒。

此外,如果您使用断点,那么当您暂停程序时,这将暂停延迟。 当您再次运行它时,它将继续它从上次中断的地方开始,并带有排队的ajax事件,使其看起来像是它们自己在运行,但实际上是上次运行遗留下来的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM