jQuery 使用 $.get 的延迟变量

jQuery deferred variable using $.get

我迷路了,不确定要查找什么。我知道这可能与 jQuery 承诺有关。所以,开门见山,我正在尝试 return 一个 "pass" 变量作为布尔值来检查电子邮件是否有效。它不是传递带有值 = "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;
        });

代码 return 为真,而应 return 为假。同样,我知道这与 $.get 请求和变量超出范围有关,我只是不确定如何推迟它。

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

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

所以不要说 pass = true|false 你需要做类似的事情:MyCallBackFunction(true|false)

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

这是对 promises 的相当具有挑战性的介绍,因此有很多评论:

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
});