Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 是否可以在不扩展/复制的情况下更新angular.js服务对象?_Javascript_Angularjs - Fatal编程技术网

Javascript 是否可以在不扩展/复制的情况下更新angular.js服务对象?

Javascript 是否可以在不扩展/复制的情况下更新angular.js服务对象?,javascript,angularjs,Javascript,Angularjs,我有2个服务,希望从第2个服务更新第1个服务中的变量。 在控制器中,我将范围变量设置为第一个服务的getter 问题是,附加到控制器的视图不会在服务变量更改时更新,除非我使用angular.extend/copy。似乎我应该可以在下面设置selectedBuilding,而不必使用extend/copy。是我做错了什么,还是你必须这样做 控制器 app.controller('SelectedBuildingCtrl', function($scope, BuildingsService) {

我有2个服务,希望从第2个服务更新第1个服务中的变量。 在控制器中,我将范围变量设置为第一个服务的getter

问题是,附加到控制器的视图不会在服务变量更改时更新,除非我使用angular.extend/copy。似乎我应该可以在下面设置
selectedBuilding
,而不必使用extend/copy。是我做错了什么,还是你必须这样做

控制器

app.controller('SelectedBuildingCtrl', function($scope, BuildingsService) {
    $scope.building = BuildingsService.getSelectedBuilding();    
});
服务1

app.factory('BuildingsService', function() {
    var buildingsList = [];
    var selectedBuilding = {};
    // buildingsList populated up here
    ...
    var setSelectedBuilding = function(buildingId) {
        angular.extend(selectedBuilding, _.find(
            buildingsList, {'building_id': buildingId})
        );
    };
    var getSelectedBuilding = function() {
        return selectedBuilding;
    };
    ...
    return {
        setSelectedBuilding: setSelectedBuilding,
        getSelectedBuilding: getSelectedBuilding    
    }
});
服务2

app.factory('AnotherService', function(BuildingsService) {
    ...
    // something happens, gives me a building id
    BuildingsService.setSelectedBuilding(building_id);
    ...
});

提前谢谢

我认为您的服务不需要延长。您应该能够直接观看服务并响应更改:

app.controller('SelectedBuildingCtrl', function($scope, BuildingsService) {
  // first function is evaluated on every $digest cycle
  $scope.$watch(function(scope){
    return BuildingsService.getSelectedBuilding();
  // second function is a callback that provides the changes
  }, function(newVal, oldVal, scope) {
    scope.building = newVal;
  }
});

有关$watch的详细信息:

执行此代码时:

$scope.building = BuildingsService.getSelectedBuilding(); 
$scope.building
复制的内存中与服务的
所选building
相同对象的引用。当您将另一个对象指定给
所选建筑
时,
$scope.building
仍然引用旧对象。这就是视图未更新的原因,您必须使用
angular.copy/extend

如果需要将新对象指定给所选建筑,可以尝试以下解决方案以避免此问题:

app.factory('BuildingsService', function() {
        var buildingsList = [];
        var building = { //create another object to **hang** the reference
            selectedBuilding : {}
         }
        // buildingsList populated up here
        ...
        var setSelectedBuilding = function(buildingId) {
            //just assign a new object to building.selectedBuilding 
        };
        var getSelectedBuilding = function() {
            return building; //return the building instead of selectedBuilding 
        };
        ...
        return {
            setSelectedBuilding: setSelectedBuilding,
            getSelectedBuilding: getSelectedBuilding    
        }
    });
使用此解决方案,您必须更新视图以替换
$scope.building
$scope.building.selectedBuilding
的绑定


在我看来,我将坚持使用
angular.copy/extend
,以避免这种不必要的复杂性。

不确定这是否对您更有效,但您可能希望了解angular事件。请参阅:。特别是
$broadcast
$emit
$on
可能会引起您的兴趣。例如,当选定的建筑发生变化时,您可以广播一个事件(例如,
selectedBuildingChanged
),该事件可能在控制器中
$on
'd做出相应的反应。@brianmarco I一开始使用
$broadcast
$on
,但它比getter/setters更难测试。团队中的其他人只是在学习angular,所以我会尽可能的把事情弄清楚。啊,好的。你有没有机会和测试人员分享你的困难?我们在应用程序中使用事件处理某些事情,但老实说,我们可能不会对它们进行深入的测试。当然,当对
$broadcast
事件进行单元测试时,我最终不得不使用jasmine的
spyOn($rootScope,'broadcast')。和callthrough()
。但是由于$rootScope调用了来自第三方插件的其他事件,因此测试涉及1。很多嘲弄或嘲笑。在整个测试过程中调用
$rootScope.$apply()
非常聪明,以确保我可以丢弃我不关心的事件并捕获我所做的事件。我觉得这太复杂了,于是想办法少用
$broadcast
。啊,我明白了。非常感谢分享。