Це ніколи не може працювати.
async
Ключове слово дозволяє await
бути використано в функції , поміченої як , async
але він також перетворює цю функцію в генератор обіцянки. Отже функція, позначена символом async
, поверне обіцянку. Конструктор з іншого боку повертає об'єкт, який він будує. Таким чином, у нас виникла ситуація, коли ви хочете повернути об'єкт і обіцянку: неможлива ситуація.
Ви можете використовувати async / await лише там, де ви можете використовувати обіцянки, оскільки вони по суті є синтаксичним цукром для обіцянок. Ви не можете використовувати обіцянки в конструкторі, оскільки конструктор повинен повернути об'єкт, який буде побудовано, а не обіцянку.
Для подолання цього є дві моделі дизайну, обидві придумані до того, як обіцянки були навколо.
Використання init()
функції. Це працює трохи як jQuery's .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);
});
}
}
Реалізація за допомогою асинхронізації / очікування:
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);
}
}
Примітка. Хоча у наведених вище прикладах ми використовуємо обіцянки для конструктора async, вони не є строго необхідними. Ви так само легко можете написати будівельника, який приймає зворотний дзвінок.
Примітка щодо виклику функцій всередині статичних функцій.
Це не має нічого спільного з конструкторами асинхронізації, але з тим, що ключове слово 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 () {}
}