-6

Given a button and it's click action set to be (in alpinejs)

<button x-on:click.prevent|debounce.3s="response = run();" type="button">Run</button>

when the run() function is defined like this:

function run() {
  // captcha();
  let data = input();
  data = confirm(data);
...
  data = request(url, data);
  return data;
}

It is a synchronous function and it works nicely.

The recaptcha documentation (https://developers.google.com/recaptcha/docs/v3) states that if the button click is to be protected with recaptcha, it has to look like:

async function captcha() {
  let resp;
  grecaptcha.ready(function() {
    grecaptcha.execute(recaptcha_site_key, {action: 'run'}).then(function(token) {
        console.log(token);
        resp = run();
    });
  });
  return resp;
}

If the click action is set to be:

<button x-on:click.prevent|debounce.3s="response = await captcha();" type="button">Run</button>

It results to this error:

enter image description here

Can you please advise what I am doing wrong?

EDIT: added the return statement in the captcha function

nskalis
  • 31
  • 4
  • The function `captcha` doesn't contain a return statement and implicitly returns `undefined`. – jabaa Jun 20 '22 at 19:30
  • @jabaa thanks. added the return statement, the error message remains the same though, any idea? – nskalis Jun 20 '22 at 20:08
  • The function `captcha` still doesn't have a return statement. The anonymous function inside the anonymous function inside `captcha` has a return statement. – jabaa Jun 20 '22 at 20:10
  • 1
    Does this answer your question? [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – jabaa Jun 20 '22 at 20:10
  • (I am processing the async/await approach) – nskalis Jun 20 '22 at 20:25
  • You're returning `resp` before it's set. That implicitly returns `undefined`. – jabaa Jun 20 '22 at 20:33
  • @jabaa can you advise a bit more, see new "edit" based on async/await syntax, I am doing sth wrong since I am getting the same error – nskalis Jun 20 '22 at 20:34
  • @jabaa how to wait till `resp` is set? – nskalis Jun 20 '22 at 20:35
  • In JavaScript you don't wait. You return a promise. You could promisify `grecaptcha.ready` applying https://stackoverflow.com/questions/22519784/how-do-i-convert-an-existing-callback-api-to-promises. Then, you could await `grecaptcha.ready` and `grecaptcha.execute` using `await`/`async`. – jabaa Jun 20 '22 at 20:36
  • @jabaa would you be so kind to post an answer? the syntax is overwhelming being honest on this one. – nskalis Jun 20 '22 at 20:46
  • This question is a duplicate. No need for another duplicate answer. – jabaa Jun 20 '22 at 20:47

1 Answers1

-1

for others that will be in the same situation as I am, here is the solution.

first step, I made the captcha function to return a promise

function captcha() {
    return new Promise(function(resolve, reject) {
      grecaptcha.ready(function() {
        grecaptcha.execute(recaptcha_site_key, {action: 'run'}).then(function(token) {
          resolve(token);
        });
      });
    });
}

second step, async/await for the variable to become available

async function run() {
  let g_recaptcha_response = await captcha();
  document.forms['params'].elements['g_recaptcha_response'].value = g_recaptcha_response;
  let data = input();
  data = confirm(data);
  if (data['error'] === true) {
    return data;
  }
  let url = `${origin}/app/json`;
  data = request(url, data);
  // note: preparing for input / next request.
  document.forms['params'].elements['token_id'].value = data['token_id'];
  return data;
}

third step, create an IIFE at the top-level

(async function(){ let response = await run(); })();
nskalis
  • 31
  • 4