Как я могу вызвать функцию после того, как 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.