【问题标题】:Passing service between controllers and directives在控制器和指令之间传递服务
【发布时间】:2013-06-19 05:38:24
【问题描述】:

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

 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 回退。

还有哪些其他方法?

【问题讨论】:

    标签: javascript angularjs angularjs-scope angularjs-service


    【解决方案1】:

    您可以做的是,将您的服务设置在范围内,即 I.E. $scope.myService = myService 然后您可以直接从 HTML 访问它。

    您还需要将 $scope 发送到您的服务,因此一旦它获取数据,您就可以运行 $scope.$apply()。

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

    $watch 只会在作用域被 $digest'd 后更新。请参阅文档here

    【讨论】:

    • 这是一个有趣的想法。我明天得试试这个。这可以与上面定义的 setSource 方法一起使用吗?例如,如果控制器 A 调用 setSource,定义 $scope.myService 的控制器 B 会接受这个吗?我明天会试试这个(当我不再喝酒的时候),但这听起来可能会奏效......谢谢
    【解决方案2】:

    这是我的最佳猜测,为什么绑定不起作用。

    最初您将数组设置为

    mySource = [];
    

    稍后当数据来自服务器时替换引用。

    mySource = success.data;
    

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

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

    【讨论】:

    • 这是针对 getAsValue、getAsFunction 还是与两者无关?那么我接下来要做的就是 mySource.splice(0) mySource.push 等。难道不需要遍历 success.data 数组并单独推送每个元素吗?这真的不会效率低下吗?另外,感谢指出错字。它已修复。
    • 功能和价值是一样的。我需要考虑一个更有效的解决方案
    • 当我考虑高效时,解决方案可能效率低下,但它并不重要,除非数组非常大。您还可以尝试返回一个复杂的对象,例如{mySource:data},这应该可以与 $watch 一起使用。但我认为简单的 clear、push、splice 方法会起作用。
    • 回过头来查看代码,将其实例化为对象而不是数组,并直接在对象上设置键都是我尝试过的事情,但都没有解决问题.事实上,即使在目前,它并没有真正填充为数组,而是作为一个对象,最初的 [] 初始化只是一个占位符,已被替换为 {} 无效。
    猜你喜欢
    • 2018-11-01
    • 1970-01-01
    • 2021-09-21
    • 1970-01-01
    • 2014-01-30
    • 2013-07-30
    • 1970-01-01
    • 2014-03-19
    • 1970-01-01
    相关资源
    最近更新 更多