首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Object.Observe同步回调

Object.Observe同步回调
EN

Stack Overflow用户
提问于 2014-07-31 09:38:30
回答 3查看 948关注 0票数 4

我一直在试验Chrome v36中的v36。我最初的意图是在我的模型中将其用于业务逻辑,但异步行为似乎使这种情况变得不可能。我将其简化为以下示例:

代码语言:javascript
复制
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。

我的问题是,“输出”在“属性更改”之前被调用。是否有任何方法使Object.Observe同步,或者我是否应该这样做更好?(顺便说一句,我使用的是AngularJS。)

这里的问题不是向DOM添加文本,也不是将文本输出到控制台。我的业务逻辑要求我在someOtherPropety更改时立即更新name,我更愿意将这个逻辑封装在我的模型中。

显然,这只是一个例子,但我有依赖于立即执行的业务规则。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-07-31 09:44:38

Object.observe,“可悲地”(下面读一读),并不执行同步任务。一旦“微任务”结束,它就会发送更改通知。

这是解释这里

多年来在web平台上的经验告诉我们,同步方法是您尝试的第一件事,因为它是最容易让您头脑清醒的方法。问题在于它创造了一个根本危险的处理模型。如果您正在编写代码,并且说,更新对象的属性,那么您并不希望在这样的情况下更新该对象的属性可能会邀请一些任意代码去做它想做的任何事情。当您在函数中间运行时,假设无效是不理想的。

因此,您的“微任务”在console.log("Output")被调用后结束,然后Object.observe通知对象上的更改。

拥有同步事件的经典方法是使用getter和setter来代替:

代码语言:javascript
复制
Person.prototype.setName = function(name) {
    this.name = name;
    console.log("Name Changed");
};

p.setName("Bob");

当然,这将迫使您为想要查看的每个属性创建getter和setter,并忘记删除和添加新属性时发生的事件。

票数 2
EN

Stack Overflow用户

发布于 2014-07-31 09:51:13

Object.observe同步运行是没有意义的。它必须阻止线程并等待某些事情发生变化。

您应该将一个回调传递给您的watch函数,以便在发生更改时执行:

代码语言:javascript
复制
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";
});

顺便说一句,如果您使用的是角(根据您的代码和篡改根本不明显),那么您不应该关心在发生更改时执行任何代码。只要您用$scope.$apply()包装代码,角就会负责更新视图等。

例如:

代码语言:javascript
复制
<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;
                        }
                    });
                });
            });
        };
    };
});

看,还有,这个短角演示

更好的是,看看这个更多的“现实世界”演示

基本上,使用O.o而不是角的脏检查的优点是节省了$$watchers,因此您的$digest周期更快、更便宜。

角也将使用这个机制(O.o)无论如何,当ES6出来。

票数 1
EN

Stack Overflow用户

发布于 2014-07-31 09:53:30

正如您所说,观察是不同步的。但是你可以让手表进行回调,并在那里更新"someOtherProperty“。像这样

代码语言:javascript
复制
$(function () {
    var p = new Person("Alice");
    p.watch(function(){
        $("#output").text("Output: "+ p.someOtherProperty);
    });
    p.name = "Bob";
    console.log("Output");
});

更新的小提琴

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25055589

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档