提交ajax请求时,如何暂时“暂停原始请求”,直到满足条件为止?

时间:2016-10-01 17:26:36

标签: javascript jquery ajax asynchronous

我想要实现一个recaptcha进程,在它们通过之前捕获所有ajax请求 - 所需的进程如下:

  1. 用户完成将导致某种类型的ajax请求的操作。
  2. 如果用户已完成重新接收过程,则ajax请求将立即继续进行
  3. 如果用户尚未完成重新处理过程,请暂时将ajax请求“暂停”,直到重新计算过程完成,然后继续执行ajax请求。
  4. 我已经把事情带到了拦截电话的状态,但是我不知道如何暂时搁置电话。这是相关的代码:

    <script>
        var captchaValidated = null;
    
        var currentRequests = [];
        $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
            if (options.url != "/ValidateCaptcha") {
                if (captchaValidated == null || captchaValidated == false) {
                    if (captchaValidated == null){
                        openRecaptcha();
                    } else {
                        verifyCaptcha(); //see async question in method
                    }
                    if (!captchaValidated) {
                        jqXHR.abort();
                    } else {
                        //let the original request proceed now - but how?!
                    }
                }
            }
        });
    
        function verifyCaptcha() {
            var grecaptcha = $("g-recaptcha-response");
            var encodedResponse;
            if (grecaptcha != null) {
                encodedResponse = grecaptcha.val();
                $.ajax({
                    async: false, //set to false so that the calling method completes rather than async - what do you think?
                    headers: headers,
                    cache: false,
                    url: "/ValidateCaptcha",
                    type: 'POST',
                contentType: 'application/json',
                success: function (data) {
                    //parse the data - did we get back true?
                    captchaValidated = data;
                },
                error: function (raw, textStatus, errorThrown) { captchaValidated = null; alert("Validate ReCaptcha Error: " + JSON.stringify(raw)); },
                data: JSON.stringify({ "encodedResponse": encodedResponse })
                });
            }
        }
    
        function invalidateCaptcha(){
            captchaValidated = null;
        }
        function openRecaptcha() {
            grecaptcha.render('recaptcha', {
                'sitekey': "thekey",
                'callback': verifyCaptcha,
                'expired-callback': invalidateCaptcha,
                'type': 'audio image'
            });
            $("#recaptchaModal").modal('show');
        }
    </script>
    

    任何有关如何进行的建议都将不胜感激,谢谢!

3 个答案:

答案 0 :(得分:2)

感谢@Loading和@ guest271314的帮助,帮助我指出正确的方向,帮助我解决问题。我已经粘贴了如何在下面完成它 - 也许它对其他人有帮助。当然,如果有人愿意权衡我的实施,请做。

<script src="https://www.google.com/recaptcha/api.js?onload=onloadCaptcha&render=explicit&hl=en" async defer></script>
<script>
    var captchaValidated = null;
    var currentRequests = [];
    var captchaPrompted = false;
    var captchaReady = false;
    var resetCaptcha = false;
    function onloadCaptcha() {
        captchaReady = true;
        captcha = grecaptcha.render('recaptcha', {
            'sitekey': '<yoursitekey>',
            'callback': verifyCaptcha,
            'expired-callback': invalidateCaptcha,
            'type': 'audio image'
        });
    }

    var deferredCaptcha = null;
    var promiseCaptcha = null;
    var captcha = null;
    function openRecaptcha() {
        if (!captchaReady) {
            setTimeout(openRecaptcha, 50);
        }
        if (captchaPrompted) {
            return;
        }
        captchaPrompted = true;
        var captchaTimer = setInterval(function () {
            if (captchaValidated != null) {
                if (captchaValidated) {
                    deferredCaptcha.resolve();
                } else {
                    deferredCaptcha.reject();
                    captchaValidated = null;
                }
            }
        }, 100);
        if (resetCaptcha) {
            captcha.reset();
        }
        deferredCaptcha = $.Deferred();
        promiseCaptcha = deferredCaptcha.promise();
        promiseCaptcha.done(function () {
            //captcha was successful
            clearInterval(captchaTimer);
            //process the queue if there's items to go through
            if (currentRequests.length > 0) {
                for (var i = 0; i < currentRequests.length; i++) {
                    //re-request the item
                    $.ajax(currentRequests[i]);
                }
            }
        });
        promiseCaptcha.fail(function () {
            //captcha failed
            clearInterval(captchaTimer);
            currentRequests = []; //clear the queue
        });
        $("#recaptchaModal").modal('show');
    }

    function verifyCaptcha() {
        resetCaptcha = true;
        var response = $("#g-recaptcha-response").val();
        var encodedResponse;
        // confirm its validity at the server end 
        $.ajax({
            headers: headers,
            cache: false,
            url: "/ValidateCaptcha",
            type: 'POST',
            contentType: 'application/json',
            success: function (data) {
                captchaValidated = data;
                if (!data) {
                    captchaPrompted = false;
                }
            },
            error: function (raw, textStatus, errorThrown) { captchaValidated = false; captchaPrompted = false; alert("WTF Validate ReCaptcha Error?!: " + JSON.stringify(raw)); },
            data: JSON.stringify({ "encodedResponse": response })
        });
    }
    function invalidateCaptcha(){
        deferredCaptcha.reject();
        captchaValidated = null;
        resetCaptcha = true;
    }

    $.ajaxSetup({
        beforeSend: function (xhr, settings) {
            if (settings.url == '/ValidateCaptcha' || captchaValidated) {
                // we're validating the captcha server side now or it's already been validated - let it through
            } else {
                if (typeof settings.nested === 'undefined'){
                    settings.nested = true; //this flag is to determine whether it's already in the queue
                    currentRequests.push(settings); //add the request to the queue to be resubmitted
                    //prompt them with the captcha
                    openRecaptcha();
                }
                return false; // cancel this request
            }
        }
    });
</script>

答案 1 :(得分:1)

$.ajaxPrefilter()使用.then()链接到openCaptcha来致电verifyCaptcha

if (captchaValidated == null){
                openRecaptcha().then(verifyCaptcha);
            }

verifyCaptcha使用带有参数.is()的{​​{1}}来检查"*"

中是否存在元素
document

if (grecaptcha.is("*")) { ,如果openRecaptcha()没有使用grecaptcha.render返回异步结果返回jQuery promise对象;否则链接到.promise()grecaptcha.render;使用$("#recaptchaModal").modal('show')

$.when()

return $("#recaptchaModal").modal('show').promise()

答案 2 :(得分:0)

这样的东西? (伪代码)

verified = false;

$('#myButton').click(function(){
  if (!verified) verify_by_captcha();
  if (verified){
    $.ajax(function(){
      type: 'post',
       url: 'path/to/ajax.php',
      data: your_data
    })
    .done(function(recd){
      //ajax completed, do what you need to do next
      alert(recd);
    });
  }
});//end myButton.click