提交ajax请求时,如何“搁置”原始请求?在满足条件之前暂时使用

When submitting an ajax request, how can you "put the original request on hold" temporarily until a condition is met?

本文关键字:请求 条件 满足 原始 如何 ajax 搁置 提交      更新时间:2023-09-26

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

  1. 用户完成一个操作,该操作将引起某种ajax请求。
  2. 如果用户已经完成了验证码过程,ajax请求将不再延迟,继续执行
  3. 如果用户还没有完成验证码过程,暂时搁置ajax请求,直到验证码过程完成,然后继续ajax请求。

我已经得到的东西的状态,我拦截呼叫,但我不知道如何把它暂时搁置。以下是相关代码:

<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>

如何进行的任何建议将不胜感激,提前感谢!

感谢@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>

$.ajaxPrefilter().then()链接openCaptcha呼叫verifyCaptcha

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

verifyCaptcha使用.is()带参数"*"检查document中是否存在一个元素

if (grecaptcha.is("*")) {

openRecaptcha(),如果grecaptcha.render不返回异步结果返回jQuery承诺对象使用.promise();else链到grecaptcha.render$("#recaptchaModal").modal('show');使用$.when()

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

return $.when(grecaptcha.render(/* parameters */)
       , $("#recaptchaModal").modal('show').promise())

像这样?(伪代码)

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