Das kann man nie funktionieren.
Das async
Schlüsselwort kann await
in einer als gekennzeichneten Funktion verwendet werden async
, konvertiert diese Funktion jedoch auch in einen Versprechen-Generator. Also eine Funktion markiert mitasync
gibt also ein Versprechen zurück. Ein Konstruktor hingegen gibt das Objekt zurück, das er erstellt. Wir haben also eine Situation, in der Sie sowohl ein Objekt als auch ein Versprechen zurückgeben möchten: eine unmögliche Situation.
Sie können async / await nur dort verwenden, wo Sie Versprechen verwenden können, da es sich im Wesentlichen um Syntaxzucker für Versprechen handelt. Sie können Versprechen in einem Konstruktor nicht verwenden, da ein Konstruktor das zu konstruierende Objekt zurückgeben muss, kein Versprechen.
Es gibt zwei Entwurfsmuster, um dies zu überwinden. Beide wurden erfunden, bevor es Versprechen gab.
Verwendung einer init()
Funktion. Dies funktioniert ein bisschen wie bei jQuery's .ready()
. Das von Ihnen erstellte Objekt kann nur innerhalb seines eigenen init
oder verwendet werdenready
Funktion Funktion verwendet werden:
Verwendung:
var myObj = new myClass();
myObj.init(function() {
// inside here you can use myObj
});
Implementierung:
class myClass {
constructor () {
}
init (callback) {
// do something async and call the callback:
callback.bind(this)();
}
}
Verwenden Sie einen Builder. Ich habe nicht gesehen, dass dies in Javascript häufig verwendet wird, aber dies ist eine der häufigsten Problemumgehungen in Java, wenn ein Objekt asynchron erstellt werden muss. Natürlich wird das Builder-Muster verwendet, wenn ein Objekt erstellt wird, das viele komplizierte Parameter erfordert. Welches ist genau der Anwendungsfall für asynchrone Builder. Der Unterschied besteht darin, dass ein asynchroner Builder kein Objekt zurückgibt, sondern ein Versprechen dieses Objekts:
Verwendung:
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();
}
Implementierung:
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);
});
}
}
Implementierung mit 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);
}
}
Hinweis: Obwohl in den obigen Beispielen Versprechen für den asynchronen Builder verwendet werden, sind diese nicht unbedingt erforderlich. Sie können genauso einfach einen Builder schreiben, der einen Rückruf akzeptiert.
Hinweis zum Aufrufen von Funktionen in statischen Funktionen.
Dies hat überhaupt nichts mit asynchronen Konstruktoren zu tun, sondern mit der Bedeutung des Schlüsselworts this
(was für Leute aus Sprachen, die Methodennamen automatisch auflösen, dh Sprachen, die das this
Schlüsselwort nicht benötigen, etwas überraschend sein kann ).
Das this
Schlüsselwort bezieht sich auf das instanziierte Objekt. Nicht die Klasse. Daher können Sie normalerweise nicht verwendenthis
statischen Funktionen verwenden, da die statische Funktion nicht an ein Objekt gebunden ist, sondern direkt an die Klasse.
Das heißt, im folgenden Code:
class A {
static foo () {}
}
Du kannst nicht tun:
var a = new A();
a.foo() // NOPE!!
Stattdessen müssen Sie es wie folgt nennen:
A.foo();
Daher würde der folgende Code zu einem Fehler führen:
class A {
static foo () {
this.bar(); // you are calling this as static
// so bar is undefinned
}
bar () {}
}
Um dies zu beheben, können Sie bar
entweder eine reguläre Funktion oder eine statische Methode erstellen:
function bar1 () {}
class A {
static foo () {
bar1(); // this is OK
A.bar2(); // this is OK
}
static bar2 () {}
}