Isso nunca pode funcionar.
A asyncpalavra-chave permite awaitser usada em uma função marcada como asyncmas também converte essa função em um gerador de promessa. Portanto, uma função marcada com asyncretornará 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 initou readyfunçã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 thisrealmente 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 thispalavra - chave).
A thispalavra-chave refere-se ao objeto instanciado. Não é da turma. Portanto, você normalmente não pode usar thisfunçõ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 baruma 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 () {}
}