Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

162
Views
Aync/await workflow: what I'm doing wrong in loading and injecting this external script?

The problem is quite simple: some calls to refresh() result in window.grecaptcha to be undefined. Not always as I said, I think because network slowdown. It's quite "hard" to debug this, and I'm also quite new to this concept, so I'm asking for some help, maybe a code fault.

class RecaptchaController {
  loadPromise;

  async refresh() {
    await this.load();
    // window.grecaptcha is (sometimes) undefined in next line
    this.element.value = window.grecaptcha.execute(this.options.siteKey, { action: 'submit' });
  }

  load() {
    if (!this.loadPromise) {
      this.context.logDebugActivity('load');

      this.loadPromise = new Promise((resolve, reject) => {
        const url = new URL(this.options.apiUrl);
        url.searchParams.append('render', this.options.siteKey);
        url.searchParams.append('hl', this.options.locale);

        const script = document.createElement('script');
        script.setAttribute('id', this.identifier);
        script.setAttribute('src', url.toString());

        // The relevant part where I'm resolving the promise
        script.addEventListener('load', resolve);
        script.addEventListener('error', reject);

        document.body.appendChild(script);
      })
    }

    return this.loadPromise;
  }
}

Error thrown is:

recaptcha_controller.js:27 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'execute')

Basically, refresh is going to be called in a submit event handler, like this:

form.addEventListener('submit', async (e) => {
   // This is NOT how the initialization works!
   // Just and example about how I'm calling refresh()
   cost recaptchaController = new RecaptchaController();

   // This is actually what is happening
   await recaptchaController.refresh();

   // Submit handling via fetch()...
});

I'm not pasting the entire code to make it simple. In addition, there is a framework behind (but it's not relevant).

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

I made a test with reCAPTCHA v3, and looking at requests in DevTools network panel, it seems reCAPTCHA itself loads another locale-specific script asynchronously. To dynamically load reCAPTCHA the way you're trying to, you need to setup a globally visible callback and pass its name to the onload parameter of api.js.

  load() {
    if (!this.loadPromise) {
      this.context.logDebugActivity('load');

      this.loadPromise = new Promise((resolve, reject) => {
        // recaptcha onload will resolve this promise
        window._recaptchaOnLoad = () => resolve();

        const url = new URL(this.options.apiUrl);
        url.searchParams.append('onload', '_recaptchaOnLoad');
        url.searchParams.append('render', this.options.siteKey);
        url.searchParams.append('hl', this.options.locale);

        const script = document.createElement('script');
        script.setAttribute('id', this.identifier);
        script.setAttribute('src', url.toString());

        // load event no longer needed
        script.addEventListener('error', reject);

        document.body.appendChild(script);
      }).finally(() => {
        // optionally delete window property
        delete window._recaptchaOnLoad;
      })
    }

    return this.loadPromise;
  }
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!