Как я могу вызвать функцию после того, как grecaptcha.execute() завершил выполнение - вызванное событием?

В настоящее время grecaptcha.execute выполняется при загрузке страницы, как в первом примере JS ниже. Если вызов reCAPTCHA вызван, это происходит, когда страница загружена. В идеале это происходит, когда вместо этого нажимается кнопка отправки формы. Итак, я попробовал это, переместив это в событие submit (второй пример JS) и поместив функцию axios в обещание. Он отправляется до того, как grecaptcha.execute завершит выполнение.

Что я здесь не понимаю? Мой первый опыт с обещаниями, так что я не понимаю, как работают обещания? Разве это не лучшее решение для этой проблемы? Это что-то еще?

HTML

<head>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" defer></script>
</head>

JS

const form = document.querySelector('#subscribe');
let recaptchaToken;
const recaptchaExecute = (token) => {
    recaptchaToken = token;
};


const onloadCallback = () => {
    grecaptcha.render('recaptcha', {
        'sitekey': 'abcexamplesitekey',
        'callback': recaptchaExecute,
        'size': 'invisible',
    });
    grecaptcha.execute();
};

    form.addEventListener('submit', (e) => {
        e.preventDefault();
        const formResponse = document.querySelector('.js-form__error-message');
        axios({
            method: 'POST',
            url: '/actions/newsletter/verifyRecaptcha',
            data: qs.stringify({
                recaptcha: recaptchaToken,
                [window.csrfTokenName]: window.csrfTokenValue,

            }),
            config: {
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
            },
        }).then((data) => {
            if (data && data.data.success) {
                formResponse.innerHTML = '';
                form.submit();
            } else {
                formResponse.innerHTML = 'Form submission failed, please try again';
            }
        });
    }

JS

const onloadCallback = () => {
    grecaptcha.render('recaptcha', {
        'sitekey': 'abcexamplesitekey',
        'callback': recaptchaExecute,
        'size': 'invisible',
    });
};

form.addEventListener('submit', (e) => {
    e.preventDefault();
    const formResponse = document.querySelector('.js-form__error-message');
    grecaptcha.execute().then(axios({
        method: 'POST',
        url: '/actions/newsletter/verifyRecaptcha',
        data: qs.stringify({
            recaptcha: recaptchaToken,
            [window.csrfTokenName]: window.csrfTokenValue,
        }),
        config: {
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        },
    })).then((data) => {
        if (data && data.data.success) {
            formResponse.innerHTML = '';
            form.submit();
        } else {
            formResponse.innerHTML = 'Form submission failed, please try again';
        }
    });
}

0 ответов

Я использую веб-службу, так как мне нужен метод, который можно было бы использовать на всех страницах. Особое внимание на то, что нужно вернуть false; и когда запрос ajax вернется, верните свой пост.

<script type="text/javascript">

   function CheckCaptcha()
    {
        grecaptcha.ready(function () {
            grecaptcha.execute('<%#RecaptchaSiteKey%>', { action: 'homepage' }).then(function (token) {
            $.ajax({
                type: "POST",
                url: "../WebServices/Captcha.asmx/CaptchaVerify", 
                data: JSON.stringify({ 'captchaToken' : token }),
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (response) {
                    __doPostBack('<%= RegisterButton.UniqueID%>', '');
                    //console.log('Passed the token successfully');
                },
                failure: function (response) {                     
                    //alert(response.d);
                }
                });
            });
       });

       return false;
    }
    </script>

Я решил это, изменив кнопку отправки на тупую кнопку и обработав все с помощью метода js:

@Html.HiddenFor(model => model.ReCaptchaToken);

<input type="button"
        value="Submit"
        onclick="onSubmit()"
/>

Метод Then() ожидает токен, помещает его в скрытое поле и только после этого вручную отправляет форму:

<script>
    if (typeof grecaptcha == 'object') { //undefined behind the great firewall
        grecaptcha.execute('@Config.ReCaptchaSiteKey', { action: 'register' }).then(function (token) {
            window.document.getElementById('ReCaptchaToken').value = token;
            $('form').submit();
        });
    } else {
        window.document.getElementById('ReCaptchaToken').value = -1;
        $('form').submit();
    }
</script>

Примечание. @Html.HiddenFor - это MVC - вы можете не использовать его. $('form') - это JQuery - вам это не обязательно нужно - также можно использовать getElementById.

Другие вопросы по тегам