【问题标题】:jQuery deferred variable using $.get使用 $.get 的 jQuery 延迟变量
【发布时间】:2017-08-04 23:18:31
【问题描述】:

我迷路了,不知道在这方面要查找什么。我知道这可能与 jQuery 承诺有关。所以,直截了当,我试图将“pass”变量作为布尔值返回,以检查电子邮件是否有效。而不是通过 value = "asdf" 传递 false,它仍然传递 true。我知道这是因为异步请求,我只是不确定如何推迟该变量。代码如下:

console.log( this.newValidate($('#forgottenPwdForm'))); // Returns true

newValidate: function(form){
    var $form  = form,
        errmsg = function(msg){
            return '<span class="error" style="text-align:right; margin: 2px 15px; color:red;">' + msg + '</span><br/>';
        };

    // Check email / username
    // Needs to run 2 validations. Is the email valid? And is it duplicate if valid
    if($form.find('.email').length)
        $form.find('.email').each(function(){
            var email = escape($(this).val().trim()),
                valid = true,
                duplicate = false,
                pass = true;

            // Check if email is valid
            $.when(
                $.get('/service/account/ajaxdata?method=validemail&emailaddr='+email, function(res){
                    console.log(res);
                    valid   = res;
                }),

                $.get('/subscribe/check_email?email=' + email, function(data) {
                    if(data){
                        duplicate   = false; }
                })

            ).then(function(){

                if(valid == 0){
                    var error = errmsg("Email is not valid.");
                    pass = false;
                    console.log(pass);
                }
                else {
                    // Now that the email is valid, we need to check if it's duplicate
                    if(duplicate == false) {
                       $('.email').addClass('emailError');
                       pass = false;
                    }
                    else {
                       if($('.email').hasClass('emailError')) {
                          $('.email').removeClass('emailError');
                          $('.email').removeClass('error');
                       }

                       pass = true;
                    }
                }

            });

            if(pass == false) return pass;
        });

代码在应该返回 false 时返回 true。同样,我知道这与 $.get 请求和变量超出范围有关,我只是不确定如何推迟它。

【问题讨论】:

  • 直到这条线 if(pass == false) return pass; 之前看起来不错,它超出了承诺,所以首先执行。当isvalid() 进行 ajax 调用时,您根本无法进行“if (isvalid()==true)”类型测试(但我怀疑您已经知道这一点)。有关更多信息,请参见此处:stackoverflow.com/questions/14220321/…
  • 我明白,但是整个方法的 newValidate 方法实际上有更多的检查,例如检查 '.required' / '.passwd' 类,并根据返回 false那些通过与否。错误的返回会阻止表单被发布(未显示)。目前正在检查该链接。

标签: jquery asynchronous promise deferred


【解决方案1】:

newValidate() 中,您正在使用承诺,因此返回一个承诺。请不要试图传入回调“because then you lose exception bubbling (the point of promises) and make your code super verbose”(@Esailija)。

这是一个相当具有挑战性的 Promise 介绍,因此有很多 cmets :

newValidate: function($form) {
    var $emailElements = $form.find('.email');
    var promises = $emailElements.map(function(index, el) { // Use `.map()` to produce an array of promises.
        var email = escape($(el).val().trim());
        return $.when(
            $.get('/service/account/ajaxdata?method=validemail&emailaddr=' + email), // no direct callback here ...
            $.get('/subscribe/check_email?email=' + email) // ... or here.
        ).then(function(valid, unique) { // Simple! The two $.get() responses appear hear as arguments.
            // The question's `data` appears to be a `unique` indicator (ie !duplicate), but the sense may be reversed?
            var pass = valid && unique; // A composite pass/fail boolean for this email element.
            if(!pass) {
                $(el).addClass('emailError');
            } else {
                $(el).removeClass('emailError');
            }
            // Note: It would be better to give the user separate indications of invalid|duplicate, so (s)he has a better clue as to what's wrong.
            return pass; // whatever is returned here will be the value delivered by the promise inserted into the `promises` array
        });
    });
    // Now use `$.when()` again to aggregate the `promises` array. 
    return $.when.apply(null, promises).then(function() {
        // Now use `Array.prototype.reduce` to scan the arguments list (booleans) and give a composite pass/fail boolean.
        var pass = Array.prototype.reduce.call(arguments, function(prev, current) {
            return prev && current;
        }, true);
        if(!pass) {
            return $.Deferred().reject(new Error(errmsg("At least one email is not valid."))).promise(); // jQuery's cumbersome way to `throw` an error from a promise chain.
        }
    });
}

调用如下:

this.newValidate($("#myForm")).then(function() {
    // pass
}, function(error) {
    // Something went wrong.
    // Expected error or unexpected error will end up here.
    consoe.log(error);
    $("#whatever").append('<div class="error">' + error.message + '</div>'); // if required
});

【讨论】:

  • 这实际上是一个更好的解释。首先,我要感谢你花时间写这个解释。其次,这绝对代表了我正在寻找的更多内容,并且只需通过您的代码阅读 cmets,我就可以看到 Promise 如何更好地工作。再次感谢您!
【解决方案2】:

您需要使用结果执行回调方法,而不是设置变量。

代码是异步运行的,因此执行会一直持续到最后,而无需执行任何验证代码,这就是为什么您总是得到 true 的原因。

所以不要说 pass = true|false 您需要执行以下操作:MyCallBackFunction(true|false)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多