这永远行不通。
async
关键字允许在被标记为async
的函数中使用await
,但它也将该函数转换成一个Promise生成器。因此,标记为async
的函数将返回一个Promise。而构造函数则返回正在构造的对象。因此我们有了一种既想返回对象又想返回Promise的情况:这是不可能的。
只能在可以使用promise的地方使用async/await,因为它们本质上是promise的语法糖。在构造函数中无法使用Promise,因为构造函数必须返回要构造的对象,而不是Promise。
有两种设计模式可以克服这个问题,它们都是在Promise出现之前发明的。
- 使用
init()
函数,这与jQuery的.ready()
函数有些相似。您创建的对象只能在其自己的init
或ready
函数中使用:
用法:
var myObj = new myClass();
myObj.init(function() {
// inside here you can use myObj
});
实现:
class myClass {
constructor () {
}
init (callback) {
callback.bind(this)();
}
}
- 使用构造器。我在javascript中很少看到这种用法,但在Java中,当需要异步构建对象时,这是更常见的解决方案之一。当然,构建器模式用于构建需要大量复杂参数的对象。这正是异步构建器的用例。区别在于异步构建器不返回一个对象,而是该对象的promise:
用法:
myClass.build().then(function(myObj) {
});
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);
}
}
注意:尽管在上面的示例中我们使用了Promise作为异步构建器,但它们并不是严格必要的。您也可以轻松编写一个接受回调函数的构建器。
关于在静态函数中调用函数的说明。
这与异步构造函数没有任何关系,而是与关键字 this
的实际含义有关(对于来自可以自动解析方法名称的语言的人来说,即不需要 this
关键字的语言,可能会感到有些惊讶)。
关键字 this
指的是被实例化的对象,而不是类。因此,在静态函数中通常无法使用 this
,因为静态函数未绑定到任何对象,而是直接绑定到类。
也就是说,在下面的代码中:
class A {
static foo () {}
}
你不能做以下事情:
var a = new A();
a.foo() // NOPE!!
相反,您需要将其称为:
A.foo();
因此,以下代码将导致错误:
class A {
static foo () {
this.bar();
}
bar () {}
}
为了解决这个问题,您可以将
bar
改为普通函数或静态方法:
function bar1 () {}
class A {
static foo () {
bar1();
A.bar2();
}
static bar2 () {}
}
.init()
这样的方法来执行异步操作。另外,由于你正在子类化HTMLElement,很可能使用此类的代码并不知道它是异步的,因此你可能需要寻找完全不同的解决方案。 - jfriend00