Cela ne peut jamais fonctionner.
Le async
mot-clé permet await
d'être utilisé dans une fonction marquée comme async
mais il convertit également cette fonction en un générateur de promesses. Ainsi, une fonction marquée avec async
renverra une promesse. Un constructeur, quant à lui, renvoie l'objet qu'il construit. Nous avons donc une situation où vous voulez à la fois rendre un objet et une promesse: une situation impossible.
Vous ne pouvez utiliser async / await que là où vous pouvez utiliser des promesses car elles sont essentiellement du sucre de syntaxe pour les promesses. Vous ne pouvez pas utiliser de promesses dans un constructeur car un constructeur doit renvoyer l'objet à construire, pas une promesse.
Il existe deux modèles de conception pour surmonter cela, tous deux inventés avant que les promesses n'existent.
Utilisation d'une init()
fonction. Cela fonctionne un peu comme jQuery .ready()
. L'objet que vous créez ne peut être utilisé qu'à l'intérieur de sa propre fonction init
ou de sa ready
fonction:
Usage:
var myObj = new myClass();
myObj.init(function() {
// inside here you can use myObj
});
La mise en oeuvre:
class myClass {
constructor () {
}
init (callback) {
// do something async and call the callback:
callback.bind(this)();
}
}
Utilisez un constructeur. Je n'ai pas vu cela beaucoup utilisé en javascript, mais c'est l'une des solutions de contournement les plus courantes en Java lorsqu'un objet doit être construit de manière asynchrone. Bien sûr, le modèle de générateur est utilisé lors de la construction d'un objet qui nécessite beaucoup de paramètres compliqués. C'est exactement le cas d'utilisation des générateurs asynchrones. La différence est qu'un générateur asynchrone ne renvoie pas un objet mais une promesse de cet objet:
Usage:
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();
}
La mise en oeuvre:
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);
});
}
}
Implémentation avec 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);
}
}
Remarque: bien que dans les exemples ci-dessus, nous utilisons des promesses pour le constructeur asynchrone, elles ne sont pas strictement nécessaires. Vous pouvez tout aussi facilement écrire un générateur qui accepte un rappel.
Remarque sur l'appel de fonctions à l'intérieur de fonctions statiques.
Cela n'a rien à voir avec les constructeurs asynchrones mais avec ce que this
signifie réellement le mot-clé (ce qui peut être un peu surprenant pour les personnes venant de langues qui font une résolution automatique des noms de méthodes, c'est-à-dire des langues qui n'ont pas besoin du this
mot - clé).
Le this
mot-clé fait référence à l'objet instancié. Pas la classe. Par conséquent, vous ne pouvez normalement pas utiliser this
à l'intérieur des fonctions statiques puisque la fonction statique n'est liée à aucun objet mais est directement liée à la classe.
C'est-à-dire dans le code suivant:
class A {
static foo () {}
}
Tu ne peux pas faire:
var a = new A();
a.foo() // NOPE!!
à la place, vous devez l'appeler comme suit:
A.foo();
Par conséquent, le code suivant entraînerait une erreur:
class A {
static foo () {
this.bar(); // you are calling this as static
// so bar is undefinned
}
bar () {}
}
Pour résoudre ce problème, vous pouvez créer bar
une fonction normale ou une méthode statique:
function bar1 () {}
class A {
static foo () {
bar1(); // this is OK
A.bar2(); // this is OK
}
static bar2 () {}
}