Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

161
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda