Esto nunca puede funcionar.
La async
palabra clave permite await
ser utilizada en una función marcada como async
pero también convierte esa función en un generador de promesas. Entonces, una función marcada con async
devolverá una promesa. Un constructor, por otro lado, devuelve el objeto que está construyendo. Por lo tanto, tenemos una situación en la que desea devolver un objeto y una promesa: una situación imposible.
Solo puede usar async / wait donde puede usar promesas porque son esencialmente azúcar de sintaxis para promesas. No puede usar promesas en un constructor porque un constructor debe devolver el objeto a construir, no una promesa.
Hay dos patrones de diseño para superar esto, ambos inventados antes de que se cumplieran las promesas.
Uso de una init()
función. Esto funciona un poco como jQuery's .ready()
. El objeto que cree solo se puede usar dentro de su propia función init
o ready
función:
Uso:
var myObj = new myClass();
myObj.init(function() {
// inside here you can use myObj
});
Implementación:
class myClass {
constructor () {
}
init (callback) {
// do something async and call the callback:
callback.bind(this)();
}
}
Usa un constructor. No he visto que esto se use mucho en JavaScript, pero esta es una de las soluciones más comunes en Java cuando un objeto debe construirse de forma asíncrona. Por supuesto, el patrón de construcción se usa al construir un objeto que requiere muchos parámetros complicados. Cuál es exactamente el caso de uso para los constructores asincrónicos. La diferencia es que un generador asíncrono no devuelve un objeto sino una promesa de ese objeto:
Uso:
myClass.build().then(function(myObj) {
// myObj is returned by the promise,
// not by the constructor
// or builder
});
// with async/await:
async function foo () {
var myObj = await myClass.build();
}
Implementación:
class myClass {
constructor (async_param) {
if (typeof async_param === 'undefined') {
throw new Error('Cannot be called directly');
}
}
static build () {
return doSomeAsyncStuff()
.then(function(async_result){
return new myClass(async_result);
});
}
}
Implementación con async / await:
class myClass {
constructor (async_param) {
if (typeof async_param === 'undefined') {
throw new Error('Cannot be called directly');
}
}
static async build () {
var async_result = await doSomeAsyncStuff();
return new myClass(async_result);
}
}
Nota: aunque en los ejemplos anteriores usamos promesas para el generador asíncrono, no son estrictamente necesarios. Puede escribir fácilmente un generador que acepte una devolución de llamada.
Nota sobre funciones de llamada dentro de funciones estáticas.
Esto no tiene nada que ver con los constructores asíncronos, sino con lo que this
realmente significa la palabra clave (lo que puede ser un poco sorprendente para las personas que provienen de idiomas que hacen resolución automática de nombres de métodos, es decir, idiomas que no necesitan la this
palabra clave).
La this
palabra clave se refiere al objeto instanciado. No la clase Por lo tanto, normalmente no puede usar this
funciones estáticas internas ya que la función estática no está vinculada a ningún objeto, sino que está vinculada directamente a la clase.
Es decir, en el siguiente código:
class A {
static foo () {}
}
Tú no puedes hacer:
var a = new A();
a.foo() // NOPE!!
en su lugar, debe llamarlo como:
A.foo();
Por lo tanto, el siguiente código provocaría un error:
class A {
static foo () {
this.bar(); // you are calling this as static
// so bar is undefinned
}
bar () {}
}
Para solucionarlo, puede hacer bar
una función regular o un método estático:
function bar1 () {}
class A {
static foo () {
bar1(); // this is OK
A.bar2(); // this is OK
}
static bar2 () {}
}