I have been experimenting with Object.observe in Chrome v36. My original intent was to use this for business logic in my models, but the asynchronous behaviour seems to make this impossible. I have boiled this down to the following example:
function Person(name) {
this.name = name;
this.someOtherProperty = null;
this.watch = function()
{
var self = this;
Object.observe(this, function(changes){
for(var i = 0; i < changes.length; i++)
{
if(changes[i].name == "name")
{
self.someOtherProperty = changes[i].newValue;
console.log("Property Changed");
}
}
});
}
}
$(function () {
var p = new Person("Alice");
p.watch();
p.name = "Bob";
$("#output").text("Output: "+ p.someOtherProperty);
console.log("Output");
});
JSFiddle link, with jQuery.
My issue is that "Output" is called before "Property Changed". Is there any way to make Object.Observe synchronous, or should I be doing this a better way? (I am using AngularJS, btw.)
The issue here is not adding text to the DOM, or outputting to the console. My business logic requires me to immediately update someOtherPropety
when name
changes, and I'd prefer encapsulating this logic in my model.
Obviously, this is just an example case, but I have business rules that rely on being executed instantly.
Object.observe
, "sadly" (read next), doesn't perform a synchronous task. It sends notifications of the changes as soon as a "micro-task" ends.This is explained here.
So, your "micro-task" ends after
console.log("Output")
has been called, thenObject.observe
notifies the changes on the object.The classic method to have synchronous events is using getters and setters instead:
Of course, that would force you to create getters and setters for every property you want to watch, and forget about events on deleting and adding new properties.