• Empleos
  • Sobre nosotros
  • profesionales
    • Inicio
    • Empleos
    • Cursos y retos
  • empresas
    • Inicio
    • Publicar vacante
    • Nuestro proceso
    • Precios
    • Evaluaciones
    • Nómina
    • Blog
    • Comercial
    • Calculadora de salario

0

216
Vistas
JavaScript wrap existing function in async one: deal with the result (automatically wrapped into a Promise)?

I'm trying to write a "mixing" for JavaScript classes (controllers, in my app) to automatically "await" for a given function to be resolved, before actually invoke the real methods. Real class methods should receive the resolved value as last argument.

Here is the code of useAwait, where i'm looking for the static class property awaits and wrapping the originalFunc into a new async one. I'm calling the new function passing the original arguments plus the asyncFn call result:

const useAwait = (controller, asyncFn) => {
  controller.constructor.awaits.forEach(func => {
    const originalFunc = controller[func];

    controller[func] = async (...args) => {
      return originalFunc.apply(
        controller,
        [...args, await asyncFn.call(controller)]
      );
    };
  });
}

So when useAwait(ctrl, this.load) is invoked on an instance this class:

class Controller {
  static awaits = ['foo', 'bar'];
  
  promise;
  
  constructor() {
    useAwait(this, this.load);
  }
  
  async foo(e, resolved) {        
    return resolved;
  }
  
  bar(resolved) {
    return resolved;
  }
  
  async load() {
    if (!this.promise) {
      this.promise = new Promise(resolve => setTimeout(() => {
        resolve('Hello World!');
      }, 3000));
    }

    return this.promise;
  }
}

The problem: all seems fine for foo (already async), but it's not for bar: the result is a Promise because now the bar is wrapped in async (wan't before). I know that an async function result is wrapped into a Promise. Codepen example where bar call outputs "[object Promise]".

So the question is: in theory, I should check if the original function is async and if it was not, await for it's return value?

almost 3 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

...in theory, I should check if the original function is async and if it was not, await for it's return value?"

It wouldn't matter, your wrapper is async; an async function always returns a promise, whether you use await or not. Moreover, your wrapper can't be synchronous, because it needs to call awaitFn (load, in the example) and wait for its result.

If you're going to wrap originalFunction (bar) such that it waits for awaitFn (load) to complete, the wrapped version of it needs to be asynchronous (either async, or return a promise explicitly [or accept a callback, but better IMHO to use promises]). It cannot be synchronous, because awaitFn (load) isn't synchronous.

If the class instance isn't ready for use when you construct it, you might consider using a static method to get an instance instead; the static instance would return a promise that it fulfills with the instance once load is complete. Rough sketch:

class Controller {
    dataFromLoadingProcess;

    constructor(dataFromLoadingProcess) {
        this.dataFromLoadingProcess = dataFromLoadingProcess;
    }

    async foo(e, resolved) {
        // ...optionally use `this.dataFromLoadingProcess`...
        return resolved;
    }

    bar(resolved) {
        // ...optionally use `this.dataFromLoadingProcess`...
        return resolved;
    }

    static async createInstance() {
        await /*...the loading process...*/;
        return new Controller(/*...data from loading process here, perhaps...*/)
    }
}
almost 3 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 Nuestro proceso Comercial
Legal
Términos y condiciones Política de privacidad
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recomiéndame algunas ofertas
Necesito ayuda