Обещание разрешается один раз - PullRequest
0 голосов
/ 28 марта 2020

Обещание в моем коде разрешается только при первом выполнении, это простая отправка формы с проверкой 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

Ответы [ 4 ]

1 голос
/ 28 марта 2020

На основе опубликованного вами кода у вас есть следующие опции:

1-й вариант использования 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))
    });

});

2-й вариант использования 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;
        }
    })
}
1 голос
/ 28 марта 2020

По ссылке, которую вы разместили, я вижу, что в вашей функции captchaVerification вы проверяете, отображалась ли ранее капча, если нет, и resolve или reject обещание. Проблема в том, что вы никогда не resolve или reject, если isRendered истинно.

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;
        }
    })
}
0 голосов
/ 31 марта 2020

Для всех, кому интересно, это кусок кода, который решил мою проблему. В основном Google API не позволяет пользователю отображать тот же объект капчи на тот же HTML элемент больше чем один раз . Я решил это, динамически создав HTML Элемент для моей капчи и удалив его после Я получил ответ от проверки на стороне сервера Google API (успех / ошибка).

https://gist.github.com/ANTOSzbk/75ed7003e914162550f61399122a3bd4

0 голосов
/ 28 марта 2020

Это чисто зависит от captchaVerification реализации. Если функция возвращает то же обещание. Это не разрешится в следующий раз. Это как 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();
...