【发布时间】:2017-08-28 10:37:44
【问题描述】:
我有一个包含 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()
一切正常,在测试期间,我向代理添加了打印输出以确定使用此类模型设计的性能影响,并且我注意到我的模型 get 是从承诺链中调用的。
示例输出如下:
<-then
<-_attributes
{"test":"test"}
我猜返回new this(query) 会导致promise 认为它可能是一个返回的promise,因此.then() 被执行。
我发现的唯一解决方法是将解析响应包装在新数组或另一个像这样的对象中:
static fetch(query = {}, opts = {}) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([new this(query)])
}, 500)
})
}
// Output
// 2
// <-_attributes
// {"test":"test"}
我想知道的是,这是正确的方法吗?还有其他解决方案可以解决这种副作用吗?
【问题讨论】:
-
您现在看到的行为到底有什么问题?传递给
resolve的值可能是“thenable”,因此它会检查.then是否存在。这是意料之中的。 -
没有错,我只是想知道这是否是预期的行为,有没有办法解决它。问题是我想防止对代理的不必要调用,因为它的性能在某些情况下是有问题的。
-
使用 "
new this(query)解析会导致承诺认为可能是返回的承诺" - 是的,完全正确。 “...因此.then()被执行” - 不,它没有被执行,因为它不存在。但它被访问,以 try 执行它,以防它是一个方法。 -
为什么会出现这个问题,您需要解决什么问题?
-
嗯..访问你是对的,我正在记录对属性的访问,我的错。这本身不是问题,但正如我在其他评论中所写的那样,当由于代理性能缓慢而使用大量承诺处理大型数据集时,它可能会成为问题。通过封装解析值来转义代理是一种可用的技巧,我只是想确保这是正确的方法,感谢 cmets..
标签: javascript ecmascript-6 es6-promise es6-proxy