Recaptcha v2重置并将其容器元素从DOM中删除时引发错误

时间:2018-10-03 00:02:53

标签: javascript recaptcha

当我显式呈现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。

我正在寻找处理上述错误或以其他方式(如果我现在做错的话)处理重新捕获的方法

2 个答案:

答案 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()方法。