对象.观察同步回调
Object.Observe Synchronous Callback
我一直在尝试使用Object。观察Chrome v36。我最初的意图是将其用于模型中的业务逻辑,但异步行为似乎使这变得不可能。我将其归结为以下示例:
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链接,使用jQuery。
我的问题是"Output"在"Property Changed"之前被调用。有没有办法使对象。观察同步,还是我应该用一种更好的方法?(我正在使用AngularJS,顺便说一句)
这里的问题不是向DOM添加文本,或者输出到控制台。我的业务逻辑要求我在name
更改时立即更新someOtherPropety
,我更愿意将此逻辑封装在我的模型中。
显然,这只是一个示例,但是我有依赖于立即执行的业务规则。
Object.observe
, "可悲的是"(阅读下一个),不执行同步任务。一旦"微任务"结束,它就会发送更改通知。
说明如下。
多年的web平台经验告诉我们,同步方法是你首先尝试的方法,因为它最容易让你理解。问题是它创建了一个从根本上危险的处理模型。如果你写代码说,更新一个对象的属性,你不希望这种情况因为更新对象的属性可能会引起一些任意代码去做它想做的事情。在你运行一个函数的过程中,让你的假设失效是不理想的。
所以,你的"微任务"在 console.log("Output")
被调用后结束, 然后 Object.observe
通知对象上的更改。
Person.prototype.setName = function(name) {
this.name = name;
console.log("Name Changed");
};
p.setName("Bob");
当然,这将迫使您为每个想要监视的属性创建getter和setter,而忘记删除和添加新属性时的事件。
正如你所说,观察是不同步的。但你可以让watch取一个回叫然后在那里更新someOtherProperty。这样的
$(function () {
var p = new Person("Alice");
p.watch(function(){
$("#output").text("Output: "+ p.someOtherProperty);
});
p.name = "Bob";
console.log("Output");
});
更新jsfiddle 让Object.observe
同步行为是没有意义的。它将不得不阻塞线程并等待一些变化。
你应该传递一个回调到你的watch
函数,以便在发生变化时执行:
this.watch = function (callback) {
var self = this;
Object.observe(this, function (changes) {
changes.forEach(function (change) {
if (change.name === 'name') {
self.someOtherProperty = change.newValue;
console.log("Property Changed");
callback();
}
});
});
}
$(function () {
var p = new Person("Alice");
p.watch(function () {
// !!!!! OF COURCE YOU SHOULD NEVER DO IT LIKE THIS IN ANGULAR !!!! //
$("#output").text("Output: " + p.someOtherProperty);
console.log("Output");
});
p.name = "Bob";
});
顺便说一句,如果你使用的是Angular(从你的代码和摆弄来看,它一点也不明显),你不应该在意在观察到变化发生时是否执行任何代码。只要你用$scope.$apply()
封装代码,Angular就会负责更新视图等。
例如:
<div ng-controller="someCtrl">
Output: {{p.someOtherProperty}}
</div>
.controller('someCtrl', function ($scope, Person) {
$scope.p = new Person('Alice');
$scope.p.watch();
$scope.p.name = 'Bob';
});
app.factory('Person', function ($rootScope) {
return function Person(name) {
var self = this;
self.name = name;
self.someOtherProperty = null;
this.watch = function () {
Object.observe(self, function (changes) {
$rootScope.$apply(function () {
changes.forEach(function (change) {
console.log(change);
if (change.name === 'name') {
self.someOtherProperty = self.name;
}
});
});
});
};
};
});
请参见这个简短的Angular演示。
更好的是,看看这个更"真实"的演示。
基本上,使用O.o
代替Angular的脏检查的好处是,你节省了$$watchers
的时间,因此你的$digest
周期更快,成本更低。
当ES6发布时,Angular也会使用这个机制(O.o
)。
- 如何制作add的回调函数或同步制作此脚本
- 同步 jQuery 调用,无需将所有内容放入回调中
- 在 Angular JS 中同步回调
- Node.js for 循环,带有回调,之后同步执行
- 同步窗口.设置超时回调
- 将函数的执行同步为 node.js 中的回调参数
- ExtJS 6 访问消息属性在存储同步的回调
- 在自定义的 for-each 循环中链接回调,同时支持同步和异步函数
- 从回调填充本地数组:同步问题
- Clojuescrapt ajax.core没有单独的处理程序/回调,代码中的流非常精确,就好像代码是同步的一样
- 如何识别回调是同步执行还是异步执行
- 函数内的两个回调函数未同步调用
- 并发AJAX回调:如何同步它们
- 在同步上下文中调用defer.notify()不会执行回调
- 对象.观察同步回调
- javascript中异步回调的结构:同步异步
- 如何使jquery的CSS操作同步(即没有回调)
- Node.js -承诺和回调Vs同步
- Javascript同步;没有回调
- 在AngularJS中,模型和视图在回调后不同步,并且$apply给出错误