Isso nunca pode funcionar.
A async
palavra-chave permite await
ser usada em uma função marcada como async
mas também converte essa função em um gerador de promessa. Portanto, uma função marcada com async
retornará uma promessa. Um construtor, por outro lado, retorna o objeto que está construindo. Portanto, temos uma situação em que você deseja retornar um objeto e uma promessa: uma situação impossível.
Você só pode usar async / waitit onde você pode usar promessas, porque elas são essencialmente sintaxe para promessas. Você não pode usar promessas em um construtor porque um construtor deve retornar o objeto a ser construído, não uma promessa.
Existem dois padrões de design para superar isso, ambos inventados antes das promessas.
Uso de uma init()
função. Isso funciona um pouco como o jQuery .ready()
. O objeto que você cria pode ser usado apenas dentro de sua própria função init
ou ready
função:
Uso:
var myObj = new myClass();
myObj.init(function() {
// inside here you can use myObj
});
Implementação:
class myClass {
constructor () {
}
init (callback) {
// do something async and call the callback:
callback.bind(this)();
}
}
Use um construtor. Não vi isso muito usado em javascript, mas essa é uma das soluções mais comuns em Java quando um objeto precisa ser construído de forma assíncrona. Obviamente, o padrão do construtor é usado ao construir um objeto que requer muitos parâmetros complicados. Qual é exatamente o caso de uso para construtores assíncronos. A diferença é que um construtor assíncrono não retorna um objeto, mas uma promessa desse 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();
}
Implementação:
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);
});
}
}
Implementação com async / waitit:
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: embora nos exemplos acima usemos promessas para o construtor assíncrono, elas não são estritamente necessárias. Você pode facilmente escrever um construtor que aceite um retorno de chamada.
Nota sobre como chamar funções dentro de funções estáticas.
Isso não tem nada a ver com construtores assíncronos, mas com o que a palavra-chave this
realmente significa (o que pode ser um pouco surpreendente para pessoas provenientes de linguagens que resolvem automaticamente nomes de métodos, ou seja, linguagens que não precisam da this
palavra - chave).
A this
palavra-chave refere-se ao objeto instanciado. Não é da turma. Portanto, você normalmente não pode usar this
funções estáticas internas, pois a função estática não está vinculada a nenhum objeto, mas diretamente à classe.
Ou seja, no seguinte código:
class A {
static foo () {}
}
Você não pode fazer:
var a = new A();
a.foo() // NOPE!!
em vez disso, você precisa chamá-lo como:
A.foo();
Portanto, o código a seguir resultaria em um erro:
class A {
static foo () {
this.bar(); // you are calling this as static
// so bar is undefinned
}
bar () {}
}
Para corrigi-lo, você pode criar bar
uma função regular ou um método estático:
function bar1 () {}
class A {
static foo () {
bar1(); // this is OK
A.bar2(); // this is OK
}
static bar2 () {}
}