grecaptcha.execute() 完成执行后如何调用函数 - 由事件触发?

Jes*_*ica 5 javascript ajax promise axios grecaptcha

当前grecaptcha.execute正在页面加载时执行,如下面的第一个 JS 示例所示。如果触发 reCAPTCHA 质询,则会在页面加载时发生这种情况。理想情况下,当单击表单提交按钮时会发生这种情况。因此,我通过将其移动到提交事件(第二个 JS 示例)并将 axios 函数放入承诺中来进行尝试。它在 grecaptcha.execute 执行完成之前提交。

我在这里不明白的是什么?我第一次接触 Promise,所以我不了解 Promise 是如何工作的吗?这不是这个问题的最佳解决方案吗?完全是别的东西吗?

HTML

<head>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" defer></script>
</head>
Run Code Online (Sandbox Code Playgroud)

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';
            }
        });
    }
Run Code Online (Sandbox Code Playgroud)

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';
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

rot*_*d86 0

我解决这个问题的方法是将提交按钮更改为哑按钮,并在 js 方法中处理所有内容:

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

<input type="button"
        value="Submit"
        onclick="onSubmit()"
/>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

注意:@Html.HiddenFor 是 MVC - 您可能不会使用它。$('form') 是 JQuery - 你不一定需要它 - 也可以使用 getElementById 。