我有一个包含 db 方法的类,它包含在处理对属性的访问的代理中。由于问题与承诺有关,因此这里是一个简化的示例代码,它重现了相同的问题:
const handler = {
ownKeys(target) {
return Object.keys(target._attributes)
},
get(target, property) {
console.log(`<-${property}`) // <-- this logs what properties are being accessed
if (typeof target[property] !== 'undefined') {
return Reflect.get(target, property)
}
return Reflect.get(target._attributes, property)
},
set(target, property, value) {
target._attributes[property] = value
return true
}
}
class User {
static table = 'users'
static fetch(query = {}, opts = {}) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(new this(query))
}, 500)
})
}
constructor(attributes = {}) {
this._attributes = attributes
return new Proxy(this, handler)
}
}
async function trigger() {
const user = await User.fetch({test:'test'})
console.log(JSON.stringify(user._attributes))
}
trigger()
一切正常,在测试期间,我向代理添加了打印输出以确定使用这种模型设计的性能影响,并且我注意到我的模型是从承诺链中调用的。
示例输出如下:
<-then
<-_attributes
{"test":"test"}
我猜想返回new this(query)
会导致承诺认为它可能是返回的承诺并因此.then()
被执行。我发现的唯一解决方法是将解析响应包装在新数组或另一个像这样的对象中:
static fetch(query = {}, opts = {}) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([new this(query)])
}, 500)
})
}
// Output
// 2
// <-_attributes
// {"test":"test"}
我想知道的是,这是正确的方法吗?对于这种副作用还有其他解决方案吗?