Я использую классы ES6 плюс Object.observer, используя MaxArt2501 implementation. У меня есть этот код ниже:EcmaScript Object.observer не уведомляет об изменениях свойств
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
.
Однако, это то, что я получил при запуске 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()
метода. Но так или иначе, похоже, что только изменение в foo.value
действительно наблюдается, но не foo.status
. Если изменить foo.status
значение «вручную» это наблюдается:
> 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)}
Я мог бы сказать, что, когда класс свойство изменяется внутри класса, она не уведомляет своего наблюдателя. Однако наблюдалось изменение foo.value
в методе bar()
.
Кто-нибудь имеет представление о том, что здесь происходит?
Спасибо,
Рафаэль Afonso
ОБНОВЛЕНИЕ - 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
на наблюдаемый метод. Однако, по-видимому, сразу после выполнения foo оба изменения свойств уведомляются.
Я думал, если бы не было лучше использовать такой подход, как Observable и Observer в Java. Кто-нибудь знает какую-то библиотеку JS, которая реализует таким образом?
UPDATE - 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);
Когда я переехала машина, я получил это:
> 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 перехватывают все виды изменений в цели, меня интересует только настройка свойств.
FYI 'Object.observe' был удален из спецификации ES6. Это устарело. – naomik
Я знаю, но я включил этот полипол для удовлетворения моих потребностей. –