承诺解决一次
Promise resolving once
我的代码中的 Promise 仅在第一次执行时解析,它是简单的表单提交和 reCAPTCHA 验证。通过调试,我知道浏览器解释器到达 await captchaVerification()
行并停在那里。第一次执行没有任何错误。
contactForm.addEventListener('submit', async (e) => {
e.preventDefault();
await captchaVerification()
const data = new FormData(contactForm)
_alert.innerHTML = 'Sending message...'
_alert.setAttribute('class', `alert show`);
ajax(contactForm.method, contactForm.action, data)
.then(([r, t]) => outcome(r ? r = 'success' : r = 'error', t))
.catch(e => outcome('error', e))
});
hastebin 的完整上下文:https://hastebin.com/oyuvoyeluv.js
从你发布的 link 我可以看到在你的 captchaVerification
函数中,你检查之前是否呈现过验证码,如果没有你呈现并且 resolve
或 reject
承诺。问题是如果 isRendered
为真,你永远不会 resolve
或 reject
。
function captchaVerification() {
return new Promise((resolve, reject) => {
captcha.style.display = 'block';
const verifyCallback = (response) => {
if (response) {
captcha.style.display = 'none'
grecaptcha.reset()
return resolve(response)
} else {
grecaptcha.reset()
return reject('Invalid captcha verification.')
}
}
// The problem is here as you do nothing if the captcha was
// previously rendered.
if (!isRendered) {
grecaptcha.render('g-recaptcha', {
'sitekey': 'my-secret-key',
'theme': 'dark',
'callback': verifyCallback
})
isRendered = true;
}
})
}
这完全取决于 captchaVerification
实施。 if function return 同样的承诺。下次解决不了。就像 Singelton
。所以最好总是创建 new promise
。
const promise = new Promise(r => setTimeout(r, 100, Math.random()))
const captchaVerification = () => promise;
const captchaVerificationRe = () => new Promise(r => setTimeout(r, 100, Math.random()));
async function main() {
let res = await captchaVerification();
console.log(res); // 0.3251446189302283
res = await captchaVerification("sffsfs");
console.log(res); // 0.3251446189302283
res = await captchaVerificationRe();
console.log(res); // 0.06299211055753262
res = await captchaVerification("sffsfs");
console.log(res); // 0.721527810718094
}
main();
根据您发布的代码,您有以下选择:
第一个选项使用 then
contactForm.addEventListener('submit', (e) => {
e.preventDefault();
captchaVerification().then((response) => {
// check if response is ok
if(response ... is not what expected end here) {
return false;
}
const data = new FormData(contactForm)
_alert.innerHTML = 'Sending message...'
_alert.setAttribute('class', `alert show`);
ajax(contactForm.method, contactForm.action, data)
.then(([r, t]) => outcome(r ? r = 'success' : r = 'error', t))
.catch(e => outcome('error', e))
});
});
第二个选项使用await
contactForm.addEventListener('submit', async (e) => {
e.preventDefault();
let response = await captchaVerification();
// check if response is ok
if(response ... is not what expected end here) {
return false;
}
const data = new FormData(contactForm)
_alert.innerHTML = 'Sending message...'
_alert.setAttribute('class', `alert show`);
ajax(contactForm.method, contactForm.action, data)
.then(([r, t]) => outcome(r ? r = 'success' : r = 'error', t))
.catch(e => outcome('error', e))
});
您也可以尝试更改 hastebin
示例中的两到三行。
var isRendered = false;
async function captchaVerification() {
return await new Promise((resolve, reject) => {
captcha.style.display = 'block'
const verifyCallback = (response) => {
if (response) {
captcha.style.display = 'none'
grecaptcha.reset()
return resolve(response)
} else {
grecaptcha.reset()
return reject('Invalid captcha verification.')
}
}
if (!isRendered) {
grecaptcha.render('g-recaptcha', {
'sitekey': 'my-secret-key',
'theme': 'dark',
'callback': verifyCallback
})
isRendered = true;
}
})
}
对于所有想知道的人来说,这是解决我的问题的一段代码。
基本上 Google API 不允许用户在 相同的 HTML 元素 上渲染 相同的验证码对象 一次。我通过为我的验证码动态创建 HTML 元素 并将其删除来解决它 after 我收到来自 Google 的响应API 服务器端验证(success/error)。
https://gist.github.com/ANTOSzbk/75ed7003e914162550f61399122a3bd4
我的代码中的 Promise 仅在第一次执行时解析,它是简单的表单提交和 reCAPTCHA 验证。通过调试,我知道浏览器解释器到达 await captchaVerification()
行并停在那里。第一次执行没有任何错误。
contactForm.addEventListener('submit', async (e) => {
e.preventDefault();
await captchaVerification()
const data = new FormData(contactForm)
_alert.innerHTML = 'Sending message...'
_alert.setAttribute('class', `alert show`);
ajax(contactForm.method, contactForm.action, data)
.then(([r, t]) => outcome(r ? r = 'success' : r = 'error', t))
.catch(e => outcome('error', e))
});
hastebin 的完整上下文:https://hastebin.com/oyuvoyeluv.js
从你发布的 link 我可以看到在你的 captchaVerification
函数中,你检查之前是否呈现过验证码,如果没有你呈现并且 resolve
或 reject
承诺。问题是如果 isRendered
为真,你永远不会 resolve
或 reject
。
function captchaVerification() {
return new Promise((resolve, reject) => {
captcha.style.display = 'block';
const verifyCallback = (response) => {
if (response) {
captcha.style.display = 'none'
grecaptcha.reset()
return resolve(response)
} else {
grecaptcha.reset()
return reject('Invalid captcha verification.')
}
}
// The problem is here as you do nothing if the captcha was
// previously rendered.
if (!isRendered) {
grecaptcha.render('g-recaptcha', {
'sitekey': 'my-secret-key',
'theme': 'dark',
'callback': verifyCallback
})
isRendered = true;
}
})
}
这完全取决于 captchaVerification
实施。 if function return 同样的承诺。下次解决不了。就像 Singelton
。所以最好总是创建 new promise
。
const promise = new Promise(r => setTimeout(r, 100, Math.random()))
const captchaVerification = () => promise;
const captchaVerificationRe = () => new Promise(r => setTimeout(r, 100, Math.random()));
async function main() {
let res = await captchaVerification();
console.log(res); // 0.3251446189302283
res = await captchaVerification("sffsfs");
console.log(res); // 0.3251446189302283
res = await captchaVerificationRe();
console.log(res); // 0.06299211055753262
res = await captchaVerification("sffsfs");
console.log(res); // 0.721527810718094
}
main();
根据您发布的代码,您有以下选择:
第一个选项使用 then
contactForm.addEventListener('submit', (e) => {
e.preventDefault();
captchaVerification().then((response) => {
// check if response is ok
if(response ... is not what expected end here) {
return false;
}
const data = new FormData(contactForm)
_alert.innerHTML = 'Sending message...'
_alert.setAttribute('class', `alert show`);
ajax(contactForm.method, contactForm.action, data)
.then(([r, t]) => outcome(r ? r = 'success' : r = 'error', t))
.catch(e => outcome('error', e))
});
});
第二个选项使用await
contactForm.addEventListener('submit', async (e) => {
e.preventDefault();
let response = await captchaVerification();
// check if response is ok
if(response ... is not what expected end here) {
return false;
}
const data = new FormData(contactForm)
_alert.innerHTML = 'Sending message...'
_alert.setAttribute('class', `alert show`);
ajax(contactForm.method, contactForm.action, data)
.then(([r, t]) => outcome(r ? r = 'success' : r = 'error', t))
.catch(e => outcome('error', e))
});
您也可以尝试更改 hastebin
示例中的两到三行。
var isRendered = false;
async function captchaVerification() {
return await new Promise((resolve, reject) => {
captcha.style.display = 'block'
const verifyCallback = (response) => {
if (response) {
captcha.style.display = 'none'
grecaptcha.reset()
return resolve(response)
} else {
grecaptcha.reset()
return reject('Invalid captcha verification.')
}
}
if (!isRendered) {
grecaptcha.render('g-recaptcha', {
'sitekey': 'my-secret-key',
'theme': 'dark',
'callback': verifyCallback
})
isRendered = true;
}
})
}
对于所有想知道的人来说,这是解决我的问题的一段代码。 基本上 Google API 不允许用户在 相同的 HTML 元素 上渲染 相同的验证码对象 一次。我通过为我的验证码动态创建 HTML 元素 并将其删除来解决它 after 我收到来自 Google 的响应API 服务器端验证(success/error)。
https://gist.github.com/ANTOSzbk/75ed7003e914162550f61399122a3bd4