Javascript 在哪里操作通过AJAX服务获取的数据?链接fn或控制器?

Javascript 在哪里操作通过AJAX服务获取的数据?链接fn或控制器?,javascript,angularjs,ajax,model-view-controller,Javascript,Angularjs,Ajax,Model View Controller,我有一个HTML部分,我也在尝试绑定AJAX数据。出于某种原因,似乎我必须将AJAX服务调用放在指令的link函数中。我不能把它放在控制器里;我在指令中这样做: link: function(scope){ MyService.getData().then(function(res){ scope.myData = res.data; }, function(res){ throw new Error('Error getting data'); }); } 首先,

我有一个HTML部分,我也在尝试绑定AJAX数据。出于某种原因,似乎我必须将AJAX服务调用放在指令的link函数中。我不能把它放在控制器里;我在指令中这样做:

link: function(scope){
  MyService.getData().then(function(res){
    scope.myData = res.data;
  }, function(res){
    throw new Error('Error getting data');
  });
}

首先,我很好奇为什么我不能在我的控制器中这样做。但是,一旦我得到数据,我还想对它进行一些操作。这一切都需要在链接函数中发生吗。在控制器中,通过
$scope.myData
循环将无法工作,因为它尚未定义?我可以在控制器中使用AJAX数据,而不必在链接文件中执行逻辑吗?

如何将其放入控制器中?我的控制器中有一个函数,我通过ng init调用它来加载数据。基于您的代码片段的示例:

.controller('myCtrl', function ($scope, MyService) {
        $scope.initData = function(){
            MyService.getData().then(function(res){
                $scope.myData = res.data;
              }, function(res){
                throw new Error('Error getting data');
              });
        }
}
然后在我的部分中,在其中一个HTML标记中:

<div ng-init="initData()"></div>


只需将ng init添加到一个HTML标记中即可发送调用。不确定这是否正确,但它适用于我的场景,也适用于你的场景。

显然有几种方法可以实现这一点;根据您的需要,有些可能比其他更好。我建议您更多地考虑您从该服务中获得的数据及其所属位置

  • 如果该数据仅由指令维护,则应继续保持代码在链接函数中的方式。将数据及其操作封装在指令中。(显然,这个选项对您的案例不起作用,但我只是解释一下什么时候这可能有意义)
  • 如果数据只需要由单个控制器访问,那么可以从指令中公开范围绑定,可以是单向的,也可以是双向的,以满足您的需要(请参阅上的“隔离指令的范围”)。通过这种方式,您可以在控制器中获取数据,并将其传递到指令中,以便对其进行“操作”
  • 如果该数据是一些指令和控制器需要访问的数据,那么它应该完全存在于服务本身中。这样,控制器或指令是否访问数据并不重要,因为它们都看到相同的数据。显然,您的问题是关于ajax调用的,所以您需要为您的服务建立一个缓存机制(签出)
  • 无论哪种方式,您都应该使用上面的(3)来提供服务。在处理本地缓存时,请注意gotchas。 希望这有帮助

    编辑: 如果您正在寻找编码示例,请让我知道——您的问题似乎更多地是关于“我的选项是什么”,而不是具体的技术实现细节


    干杯

    您可以从控制器调用该服务

    你不能去的原因是什么

    YourController.$inject = ['MyService', '$scope'];
    function YourController(myService, $scope) {
    
        myService.getData().then(
            function(res) { 
                $scope.myData = res.data;
                // or manipulate the data
                $scope.apply(); 
            })
    }
    

    您可以在指令的控制器中执行此操作,例如:

    app.directive('output', function() {
      return {
        retrict:'E',
        replace:true,
        template:'<pre>[{{MyData | json}}]</pre>',
        scope:true,
        controller:function(MyService, $scope) {
          $scope.MyData = $scope.MyData || {};
          MyService.getData().then(function(value){
            $scope.MyData.value = value;
          });
        },
        link:function(scope, element, attrs) {
          scope.MyData = scope.MyData || {};
        }
      };
    });
    
    app.directive('output',function(){
    返回{
    检索:'E',
    替换:正确,
    模板:“[{MyData | json}}]”,
    
    app.directive('myPartial', function() {
      return {
        restrict:'AE',
        template:'<pre>[{{myData| json}}]</pre>',
        scope:true,   
        link:function(scope, elem, attrs) {
          /*avoid using model manipulation in link function as it is mostly used 
    
          for DOM manipulation such as angular.element(elem).addClass('myTemplateClass');*/
        },
        controller: function($scope,MyService){
             MyService.getData().then(function(dataFromServer){
                 scope.myData = dataFromServer;
             }, function(err){
                throw new Error('Error getting data : ' + err);
             });
        }
      };
    });
    
    范围:正确, 控制器:功能(MyService,$scope){ $scope.MyData=$scope.MyData | |{}; MyService.getData().then(函数(值){ $scope.MyData.value=值; }); }, 链接:函数(范围、元素、属性){ scope.MyData=scope.MyData | |{}; } }; });

    看看这把小提琴:

    这项任务可以用各种方式完成,但问题是哪种做法最好。 首先,如果您有一个带有partial的指令,并且希望绑定到它,那么可以在该指令的控制器中进行绑定

    app.factory('MyService',function($http,$q){
    
         var _modifyGetData = function(serverData){
            // modify your data here...
            // for example -> serverData.usersCount = serverData.users.length;
            return serverData;
         };
         var getData = function(){
             var dfd = $q.defer();
             $http.get(/*Some url here*/).then(function(res){
                  var data = res.data;
                  // manipulate all your data using a function maybe
                  data = _modifyGetData(data);
                  dfd.resolve(data);   //resolve the modified data
    
    
             });
             return dfd.promise;
         }
         return {
            getData:getData
         };
    });
    
    希望这有帮助

    一些在线资源可能会有所帮助:

    我认为最好立即在控制器中调用函数,而不是将其放入ng init中。如果您输入ng init,它将在div被渲染时被调用,但我不认为这有什么帮助。@sniels谢谢您的输入,您的推理是有意义的。我需要自己尝试这种方法。我认为链接函数在这种情况下是无用的,如果$scope.myData已经有值,我只需删除链接函数和控制器中的检查。您也错误地使用了scope选项,可能应该删除它。除此之外,这似乎是一个很好的答案。@sniels关于link你是对的:多余的。。。关于作用域,你错了:@malix我不认为他错了,controller和link的作用域是相同的,即使是隔离的。不同的是,控制器是在渲染前执行的,链接是在渲染后完成的,所以在链接函数中,您应该执行所有的DOM操作。查看我的plunker@maurycy我知道。。。我的回答是“您也错误地使用了scope选项,应该删除它。”而
    scope:true
    在文档中显然是允许的……您应该在服务的回调函数中操作数据。基本上,在设置scope.myData之前。在控制器中执行此操作应该没有问题,因此我建议您将其放在那里,因为链接函数用于不同的原因。如果您可以将控制器从不必要的逻辑中剥离出来,则这是最佳做法。控制器是视图的驱动者,服务和工厂是放置额外逻辑的地方,比如数据操纵,正好@maurycy。谢谢你的评论和支持答案。直截了当。正是我需要的。非常感谢。