Это никогда не может работать.
async
Ключевое слово позволяет await
быть использовано в функции , помеченной как , async
но он также преобразует эту функцию в генератор обещания. Таким образом, функция, отмеченная знаком async
, вернет обещание. С другой стороны, конструктор возвращает объект, который он создает. Таким образом, у нас есть ситуация, когда вы хотите вернуть объект и обещание: невозможная ситуация.
Вы можете использовать async / await только там, где можете использовать обещания, потому что они по сути являются синтаксическим сахаром для обещаний. Вы не можете использовать обещания в конструкторе, потому что конструктор должен возвращать конструируемый объект, а не обещание.
Для преодоления этого есть два конструктивных шаблона, оба были изобретены до того, как обещания были выполнены.
Использование init()
функции. Это работает немного как JQuery .ready()
. Созданный вами объект можно использовать только внутри его init
илиready
функции:
Использование:
var myObj = new myClass();
myObj.init(function() {
// inside here you can use myObj
});
Реализация:
class myClass {
constructor () {
}
init (callback) {
// do something async and call the callback:
callback.bind(this)();
}
}
Используйте строителя. Я не видел, чтобы это часто использовалось в javascript, но это один из наиболее распространенных обходных путей в Java, когда объект должен быть создан асинхронно. Конечно, шаблон строителя используется при построении объекта, который требует много сложных параметров. Это именно тот случай использования для асинхронных сборщиков. Разница в том, что асинхронный компоновщик возвращает не объект, а обещание этого объекта:
Использование:
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();
}
Реализация:
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);
});
}
}
Реализация с 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);
}
}
Примечание: хотя в приведенных выше примерах мы используем обещания для асинхронного компоновщика, они не являются строго говоря необходимыми. Вы можете так же легко написать конструктор, который принимает обратный вызов.
Примечание о вызове функций внутри статических функций.
Это не имеет ничего общего с асинхронными конструкторами, но с тем, что на this
самом деле означает ключевое слово (что может быть немного удивительно для людей, пришедших из языков, которые выполняют автоматическое разрешение имен методов, то есть языков, которым this
ключевое слово не нужно ).
this
Ключевое слово относится к экземпляру объекту. Не класс. Поэтому вы не можете нормально использовать this
внутри статических функций, так как статическая функция не привязана ни к какому объекту, а напрямую связана с классом.
То есть в следующем коде:
class A {
static foo () {}
}
Вы не можете сделать:
var a = new A();
a.foo() // NOPE!!
вместо этого вам нужно назвать это как:
A.foo();
Следовательно, следующий код может привести к ошибке:
class A {
static foo () {
this.bar(); // you are calling this as static
// so bar is undefinned
}
bar () {}
}
Чтобы исправить это, вы можете сделать bar
обычную функцию или статический метод:
function bar1 () {}
class A {
static foo () {
bar1(); // this is OK
A.bar2(); // this is OK
}
static bar2 () {}
}