当我显式呈现Recaptcha v2,然后在将其从DOM中删除之前将其重置时,约40秒后,我在浏览器控制台中看到错误。
我有一个JSFiddle,可用于重现该问题。
这是相关的代码摘录:
const recaptchaHolder = document.getElementById('...');
const recaptchaWidgetId = grecaptcha.render(recaptchaHolder, {/*...*/});
// then later
grecaptcha.reset(recaptchaWidgetId);
recaptchaHolder.parentElement.removeChild(recaptchaHolder);
我得到的错误是:
未捕获(承诺)超时
具有以下stacktrace(实际的stacktrace可能会因代码紧凑而发生变化):
setTimeout (async)
J @ recaptcha__en.js:100
(anonymous) @ recaptcha__en.js:285
tb @ recaptcha__en.js:284
mj @ recaptcha__en.js:456
(anonymous) @ recaptcha__en.js:458
我尝试利用the documentation中的'error-callback'
参数来捕获此错误,但这无济于事-该错误仍未被发现,并且此回调未得到调用。
另一个观察结果:如果我在从DOM中删除元素之前忽略了调用grecaptcha.reset
,则不会发生该错误。 但是,这可能会导致UI不一致:如果用户受到Recaptcha的挑战(例如,使用图像),并且只是从DOM中删除了该元素而未调用grecaptcha.reset
,那么挑战就来了无法从DOM中清除HTML。
我正在寻找处理上述错误或以其他方式(如果我现在做错的话)处理重新捕获的方法
答案 0 :(得分:0)
许多小时后,我仅找到此解决方案,请参阅https://jsfiddle.net/4mLhcksq/
在setTimeout
之前有grecaptcha.reset()
和60秒(我想可能会更短)暂停,然后在删除Recaptcha元素之前又有一个暂停。实际上,即使我不删除Recaptcha元素,而只是重置它,我也遇到了同样的问题。
const holder = getRecaptchaHolder();
holder.style.display = 'none'; //element disappears for users
setTimeout(function() {
grecaptcha.reset(recaptchaWidgetId);
setTimeout(function() { //we have to wait a while before removing element
holder.parentElement.removeChild(holder);
}, 1000);
}, 60000);
我并不为此解决方案感到特别自豪。让我们希望有人会提供更好的。
答案 1 :(得分:-2)
抛出该错误是因为captcha已向google发送了呼叫,并且它希望接收响应,但是由于我们删除了该元素,因此响应不会按照计划进行,并且引发了区域错误,一种更好的方法是仅隐藏收到firebase.auth.signInWithPhoneNumber
函数的响应后,就会出现验证码。无需设置任何超时并在页面的destroy事件中调用captcha.clear()
方法。