在控制器和指令之间传递服务

Passing service between controllers and directives

本文关键字:服务 之间 指令 控制器      更新时间:2023-09-26

我有一个单独的服务定义如下:

 angular.module('myApp')
     .factory('myService', function ($resource, $q) {
         mySource = [];
         EndPoint = $resource('/my/api/endpoint', {});
         return({
              getSourceAsFunction: function(){
                  return(mySource);
              }
              ,getSourceAsValue: mySource,
              ,setSource: function(newSource){
                     mySource=newSource;
              }
              ,fetchSource: function(attributes){
                  request = $q.defer
                  EndPoint.get(attributes
                  ,function(success){
                          request.resolve(success.data);
                          //mySource['headersArray'] = success.data['headersArray'];
                          //mySource['footersArray'] = success.data['footersArray'];
                  },function(failure){
                          request.reject(failure);
                  });
                  request.promise
           });
      });

这个服务然后被注入到多个控制器中,在不同的指令上(其中一些具有隔离作用域)。其中只有一个(到目前为止)实际执行了获取(和结果集)操作,但是获取操作可以通过点击交互由用户重复执行。

其他控制器绑定如下:

      $scope.fooVar = myService.getSourceasValue;

      $scope.fooVar = myService.getSourceAsFunction();

在这两种情况下,当服务中的值发生变化时,变量都不会自动更新。

设置$watch如下:

       $scope.$watch('fooVar', function(newVal, oldVal){console.log('hi')}, true);

也从不触发(在两种情况下)。

资源回调中的注释行:

       //mySource['headersArray'] = success.data['headersArray'];
       //mySource['footersArray'] = success.data['footersArray'];

mySource在那时被实例化为{}。这没有解决问题。

是前一次尝试重用相同对象的尝试。

我找到的一种绕过这个限制的方法是像这样设置一个$watch:
       $scope.$watch(function(){return(myService.getSourceAsFunction())}
                  , function(newVal, oldVal){console.log('hi'), true)};

然而,我发现这令人担忧,因为我不希望这个函数在后台持续运行。(这是怎么回事?这个函数多久运行一次?触发多少次$digest迭代?这个解决方案到底有多有效?

我怎样才能绕过这个?如果您愿意,我如何"通过引用"绑定到服务变量?

是否有更好的方法?我已经尝试过事件,但是由于这些元素中的一些是兄弟元素,这导致了一个过于复杂的链,其中子元素可能$emit向上有一个侦听器在联合父元素上捕获事件,而$broadcast向下。

还有什么其他方法?

您可以做的是,将您的服务设置在作用域下,即$scope。myService = myService,然后你可以直接从HTML中访问它。

你还需要将$scope发送给你的服务,这样一旦它获取数据,你就可以运行$scope.$apply()。

现在的问题是你在控制器初始化时设置它。控制器将不会再次初始化,因此它将永远不会更新。

$watch只有在作用域被$digest后才会被更新。参考文档

这是我最好的猜测,为什么绑定不工作。

最初你将数组设置为

mySource = [];

当数据来自服务器时,您将替换引用。

mySource = success.data;

你可以尝试mySource.push方法来更新初始数组中的数据。

还想指出,第一个$watch表达式应该将第一个参数作为变量名字符串,而不是变量本身。