EcmaScript Object.observer 未通知 属性 更改
EcmaScript Object.observer is not notifying property changes
我正在使用 ES6 classes 加上 Object.observer, using the MaxArt2501 implementation。我有以下代码:
const READY = Symbol("Ready");
const RUNNING = Symbol("Running");
class Foo {
constructor() {
this.value = 1;
this.status = READY;
}
bar() {
this.status = RUNNING;
console.log("bar", this.status );
this.value = this.value + 10;
this.status = READY;
console.log("bar", this.status );
}
}
let foo = new Foo();
Object.observe(foo, function(changes) {
changes.forEach(function(change) {
console.log("foo: ", change);
});
});
我的预期是,当我执行bar()
方法时,观察者函数将被调用3次:当将foo.status
从READY
更改为RUNNING
时,当更改 foo.value
以及将 foo.status
从 RUNNING
更改为 READY
.
但是,这是我在 运行ning bar()
时得到的(在 Chrome 控制台中):
> foo
Foo {value: 1, status: Symbol(Ready)}
> foo.bar()
bar Symbol(Running)
bar Symbol(Ready)
undefined
foo: Object {name: "value", type: "update", object: Foo, oldValue: 1}
> foo
Foo {value: 11, status: Symbol(Ready)}
未定义的是bar()
方法中的return。但无论如何,看起来只是 foo.value
的变化被真正观察到了,而不是 foo.status
。
如果我更改 foo.status
值 "manually",则会观察到:
> foo.status = RUNNING
Symbol(Running)
foo: Object {name: "status", type: "update", object: Foo, oldValue: Symbol(Ready)}
> foo
Foo {value: 11, status: Symbol(Running)}
> foo.status = READY
Symbol(Ready)
foo: Object {name: "status", type: "update", object: Foo, oldValue: Symbol(Running)}
> foo
Foo {value: 11, status: Symbol(Ready)}
我可以说,当 属性 class 在 class 内部发生变化时,它不会通知它的观察者。但是,观察到 bar()
方法中的 foo.value
变化。
有人知道这里发生了什么吗?
谢谢,
拉斐尔·阿方索
更新 - 06/06
我做了一个解决方法,虽然不是很优雅,但我可以在我的实际实现中用作基础:
const READY = Symbol("Ready");
const RUNNING = Symbol("Running");
class Foo {
constructor() {
this.value = 1;
this.status = READY;
}
bar() {
// this.status = RUNNING;
console.log("bar", this.status );
this.value = this.value + 10;
// this.status = READY;
console.log("bar", this.status );
}
}
let foo = new Foo();
Object.observe(foo, function(changes) {
changes.forEach(function(change) {
if(change.name === 'value') {
change.object.status = RUNNING;
}
console.log("foo: ", change);
});
});
当我 运行 时,我得到了这个:
> foo.bar()
bar Symbol(Ready)
bar Symbol(Ready)
undefined
foo: Object {name: "value", type: "update", object: Foo, oldValue: 1}
foo: Object {name: "status", type: "update", object: Foo, oldValue: Symbol(Ready)}
如您所见,我更改了 foo.status
in observable 方法。但是,显然在 foo 执行之后,两个属性更改都会收到通知。
我在想,如果使用 Java 中的 Observable and Observer 这样的方法会不会更好。有人知道以这种方式实现的一些 JS 库吗?
更新 - 06/06 (2)
按照建议,我尝试使用代理:
const READY = Symbol("Ready");
const RUNNING = Symbol("Running");
class Foo {
constructor() {
this.value = 1;
this.status = READY;
}
bar() {
this.status = RUNNING;
// console.log("bar", this.status );
this.value = this.value + 10;
this.status = READY;
// console.log("bar", this.status );
}
}
let observer = {
set: function(obj, prop, value) {
let oldValue = obj[prop];
let result = Reflect.set(obj, prop, value);
console.log(prop + ": " + oldValue.toString() + " -> " + value.toString());
return result;
}
}
let foo = new Proxy(new Foo(), observer);
当我 运行ned 时,我得到了这个:
> foo.bar()
status: Symbol(Ready) -> Symbol(Running)
value: 1 -> 11
status: Symbol(Running) -> Symbol(Ready)
undefined
> foo.bar()
status: Symbol(Ready) -> Symbol(Running)
value: 11 -> 21
status: Symbol(Running) -> Symbol(Ready)
undefined
的确,这就是我要找的。虽然 Object.observer 目标是拦截目标中的各种变化,但我只对属性设置感兴趣。
快速浏览一下该存储库 suggests 每帧仅执行一次更新(在具有此类概念的环境中)或每 17 毫秒执行一次。
因为 JavaScript 是单线程的,如果您更改 属性 然后在单个不间断函数(即不是生成器等)中将其更改回来,它将不会被观察到这个包。
请记住,Object.observe 不再有望成为该语言的一部分。拟议规范的实际实现可能会为您提供每个事件的通知,但不可能针对这种特定情况进行伪造(至少在不将每个对象包装在代理中的情况下)。
我正在使用 ES6 classes 加上 Object.observer, using the MaxArt2501 implementation。我有以下代码:
const READY = Symbol("Ready");
const RUNNING = Symbol("Running");
class Foo {
constructor() {
this.value = 1;
this.status = READY;
}
bar() {
this.status = RUNNING;
console.log("bar", this.status );
this.value = this.value + 10;
this.status = READY;
console.log("bar", this.status );
}
}
let foo = new Foo();
Object.observe(foo, function(changes) {
changes.forEach(function(change) {
console.log("foo: ", change);
});
});
我的预期是,当我执行bar()
方法时,观察者函数将被调用3次:当将foo.status
从READY
更改为RUNNING
时,当更改 foo.value
以及将 foo.status
从 RUNNING
更改为 READY
.
但是,这是我在 运行ning bar()
时得到的(在 Chrome 控制台中):
> foo
Foo {value: 1, status: Symbol(Ready)}
> foo.bar()
bar Symbol(Running)
bar Symbol(Ready)
undefined
foo: Object {name: "value", type: "update", object: Foo, oldValue: 1}
> foo
Foo {value: 11, status: Symbol(Ready)}
未定义的是bar()
方法中的return。但无论如何,看起来只是 foo.value
的变化被真正观察到了,而不是 foo.status
。
如果我更改 foo.status
值 "manually",则会观察到:
> foo.status = RUNNING
Symbol(Running)
foo: Object {name: "status", type: "update", object: Foo, oldValue: Symbol(Ready)}
> foo
Foo {value: 11, status: Symbol(Running)}
> foo.status = READY
Symbol(Ready)
foo: Object {name: "status", type: "update", object: Foo, oldValue: Symbol(Running)}
> foo
Foo {value: 11, status: Symbol(Ready)}
我可以说,当 属性 class 在 class 内部发生变化时,它不会通知它的观察者。但是,观察到 bar()
方法中的 foo.value
变化。
有人知道这里发生了什么吗?
谢谢,
拉斐尔·阿方索
更新 - 06/06
我做了一个解决方法,虽然不是很优雅,但我可以在我的实际实现中用作基础:
const READY = Symbol("Ready");
const RUNNING = Symbol("Running");
class Foo {
constructor() {
this.value = 1;
this.status = READY;
}
bar() {
// this.status = RUNNING;
console.log("bar", this.status );
this.value = this.value + 10;
// this.status = READY;
console.log("bar", this.status );
}
}
let foo = new Foo();
Object.observe(foo, function(changes) {
changes.forEach(function(change) {
if(change.name === 'value') {
change.object.status = RUNNING;
}
console.log("foo: ", change);
});
});
当我 运行 时,我得到了这个:
> foo.bar()
bar Symbol(Ready)
bar Symbol(Ready)
undefined
foo: Object {name: "value", type: "update", object: Foo, oldValue: 1}
foo: Object {name: "status", type: "update", object: Foo, oldValue: Symbol(Ready)}
如您所见,我更改了 foo.status
in observable 方法。但是,显然在 foo 执行之后,两个属性更改都会收到通知。
我在想,如果使用 Java 中的 Observable and Observer 这样的方法会不会更好。有人知道以这种方式实现的一些 JS 库吗?
更新 - 06/06 (2)
按照建议,我尝试使用代理:
const READY = Symbol("Ready");
const RUNNING = Symbol("Running");
class Foo {
constructor() {
this.value = 1;
this.status = READY;
}
bar() {
this.status = RUNNING;
// console.log("bar", this.status );
this.value = this.value + 10;
this.status = READY;
// console.log("bar", this.status );
}
}
let observer = {
set: function(obj, prop, value) {
let oldValue = obj[prop];
let result = Reflect.set(obj, prop, value);
console.log(prop + ": " + oldValue.toString() + " -> " + value.toString());
return result;
}
}
let foo = new Proxy(new Foo(), observer);
当我 运行ned 时,我得到了这个:
> foo.bar()
status: Symbol(Ready) -> Symbol(Running)
value: 1 -> 11
status: Symbol(Running) -> Symbol(Ready)
undefined
> foo.bar()
status: Symbol(Ready) -> Symbol(Running)
value: 11 -> 21
status: Symbol(Running) -> Symbol(Ready)
undefined
的确,这就是我要找的。虽然 Object.observer 目标是拦截目标中的各种变化,但我只对属性设置感兴趣。
快速浏览一下该存储库 suggests 每帧仅执行一次更新(在具有此类概念的环境中)或每 17 毫秒执行一次。
因为 JavaScript 是单线程的,如果您更改 属性 然后在单个不间断函数(即不是生成器等)中将其更改回来,它将不会被观察到这个包。
请记住,Object.observe 不再有望成为该语言的一部分。拟议规范的实际实现可能会为您提供每个事件的通知,但不可能针对这种特定情况进行伪造(至少在不将每个对象包装在代理中的情况下)。