【问题标题】:Accessing $scope in AngularJS factory?在 AngularJS 工厂中访问 $scope?
【发布时间】:2014-03-03 22:46:29
【问题描述】:

我是AngularJS的新手,觉得它很有趣,但是我对以下情况有点不清楚。

app.factory('deleteFac', function($http){

var factory = {}; 

factory.edit = function(id){
  $http.get('?controller=store&action=getDetail&id=' + id).
    success(function(data, status){
        /** 
        got an error on the following 
        when i use return data; and i get data undefined 
        in the controller which i get it because its doing a ajax call
        you don't get data until the call first.
        **/
        $scope.detail = data;
      })
    }

return factory;
})

当我分配给$scope 并使用返回数据时出现错误,我是否可以将返回数据分配给$scope

【问题讨论】:

  • 你没有注入 $scope
  • 呃……你在说什么范围?工厂没有范围——它是一种服务。您应该在 AJAX 调用中编辑 return 承诺,并从您需要的任何有范围的地方调用它。
  • 您是在控制器内部使用这个工厂吗?如果是这样,只需将控制器的作用域作为参数传递给edit,或者接受一个传递data 的回调。你不能注入 $scope 因为它不知道要注入什么范围。
  • @BenjaminGruenbaum 我说的是控制器中的 $scope 吗?你能为我提供一个如何处理这种情况的例子吗?非常感谢您的解释。
  • @Dudi 不是好主意 参考正确答案

标签: javascript angularjs


【解决方案1】:

您通常不会在工厂、服务或提供商中使用$scope。通常,您会返回 promise(由 $http 返回),然后在控制器中处理承诺(您确实有 $scope)。

factory.edit = function(id){
    return $http.get('?controller=store&action=getDetail&id=' + id);
}

控制器功能:

$scope.edit = function(id) {

    deleteFac.edit(id).then(function(response) {
        $scope.something = response.model;
    });
}

【讨论】:

  • @bluebill1049 这就是我在评论中的意思。在这种情况下,这是正确的答案 - 我会使用 .done.then 而不是 .success 但除此之外,这是很好的 imo。
  • 最好用then而不是success更新这个答案,因为success现在已被弃用:docs.angularjs.org/api/ng/service/$http#deprecation-notice
  • 为什么不将$scope作为参数传递给函数edit(),如下factory.edit = function(id, $scope){ return $http.get('?controller=store&action=getDetail&id=' + id); },然后你可以在工厂函数中使用$scope做任何你想做的事情。
【解决方案2】:

我猜你是这个意思:

app.factory('deleteFac', function($http){

  var service = {}; 

   factory.edit = function(id, success, error){
        var promise = $http.get('?controller=store&action=getDetail&id=' + id);
        if(success)
           promise.success(success);
        if(error)
           promise.error(error);
   };

   return service;
});

然后在您的控制器中执行以下操作:

function MyController($scope, deleteFac){
   deleteFac.edit($scope.id, function(data){
       //here you have access to your scope.
   });
}

【讨论】:

  • 是的,谢谢 Edwin 我的意思是这个,谢谢你的例子
  • -1 这是一个反承诺模式。返回 promise 不太容易出错,通常更可取。
  • @BenjaminGruenbaum 介意提供参考吗?
  • 当然,我之前在这里留下了this,但删除了它,因为它真的很简单。这是使用 Promise 作为美化的回调,更不用说那里多余的 if 检查了。我认为大卫的解决方案效果很好。
  • @EdwinDalorzo 如果有人要写一本关于 JS 承诺的(好)书,那么变化是它将是大约 100 个非常具体的人之一。我上面列出的三个很可能在该列表的前 10 位。 Kris 在 JS 中普及了 Promise,编写了令人惊叹的 Q 库,使这一切成为可能它们在 NodeJS 的狭窄地方确实可行。问题是这个领域在 JS 中发展得非常快,而书籍不能很好地工作:)
【解决方案3】:

以下技巧是一个非常糟糕的做法,但如果你赶时间,你可以使用它:

$scope 替换为:angular.element('[ng-controller=CtrlName]').scope()

【讨论】:

  • 这看起来很脏,但可能是个小把戏 :) 无论如何感谢您的回答(另外你说这是一种 badddddd 做法)
  • 这是 2017 年。如果这个答案对您有帮助,并且您刚刚开始您的项目,您可能需要考虑 vue.js。
【解决方案4】:

就我个人而言,我想使用工厂的作用域,因此,我不会将作用域作为参数从调用 factory.function() 的客户端传递给它。

我在尝试使用 $scope.watch(...) 时也遇到了同样的问题,因为我们不能直接从工厂或服务中使用 $scope,但我想让它以这种方式工作,所以这就是为什么我刚刚更新了我的函数以将范围作为参数并让工厂的客户发送 $scope。所以,这将是我的解决方案:

var app = angular.module("myApp", []);

app.factory('MyFactory', function($http) {

      var factory = {};
      //This is only for my own issue I faced.
      factory.Images = {};

      factory.myFunction = function(id, scope) {
        //This is an example of how we would use scope inside a factory definition
        scope.details = "Initial Value";
        //In my case I was having this issue while using watch
        scope.$watch('details' , function(newValue, oldValue) {
          if(oldValue){
             scope.log = "Details was updated to : " +newValue;
            }
        });
        
        scope.details = "My Id is: "+id;
       };
        return factory;
});

//Controller: Factory's Client.
app.controller("MyController", ['$scope', 'MyFactory', function($scope, MyFactory) {
  
        MyFactory.myFunction(5, $scope);
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyController">
  <span>{{details}} </span>
  <hr>
  <p>{{log}} </p>
</div>

我希望这会有所帮助。 问候。

【讨论】:

    【解决方案5】:

    我认为这是最干净的解决方案:

    如果有问题或改进,请告诉我。

    (function(){
      angular.controller('controllerName', controllerName);
      controllerName.$inject = ['$scope', factory];
    
      function controllerName($scope, factory){
        var vm = this;
    
        vm.data = factory.alertPopup();
      }
    
      angular.factory('factory', factory);
      factory.$inject = ['externalServices'];
    
      function factory(externalServices){
        return {
          returnData : returnData
        }
    
        function returnData(){
          return externalServices.whatever();
        }
      }
    })();
    

    【讨论】:

      【解决方案6】:
      .factory('POPUP', function($ionicLoading, $ionicPopup) {
        var self = this;
        // THIS BLOCK SCREEN ! for loading ! Be carefoull !! ( deprecated: assign this to a var for security)
        self.showLoading = function(title, message, scope){
        scope.loading = true;
        return $ionicLoading.show({ content: message, showBackdrop: false });
        };
        self.hideLoading = function(title, message, scope){
        scope.loading = false;
        return $ionicLoading.hide();
      };
      
      // NOT BLOCK SCREEN- SIMPLE ALERTS - Standards popups
      self.showAlert = function(title, message, callback){
        var alertPopup = $ionicPopup.alert({ title: title, template: message });
        alertPopup.then(function(res) {
            console.log('callback popup');
            if (callback){ callback(); }
        });
      };
       self.showConfirm = function(objectPopup, callback){
       if (objectPopup === undefined){ objectPopup = { title: 'test confirm    Popup', template: 'Message test Confirm POPUP' }; }
       var alertPopup = $ionicPopup.confirm(objectPopup);
       alertPopup.then(function(res) {
         if (res) { callback(true); }
          else { callback(false); }
       });
       };
         return self;
         }) 
      

      【讨论】:

      • 注意:社区 wiki 在被投票时不会给予声誉。
      【解决方案7】:

      我知道这个问题很老,但这对我有用

      app.factory('myFactory',function(){
      
          let toRet = {
              foo: foo
          }
      
          return toRet;
      
          function foo(){ // This function needs to use passed scope.
              let $scope = toRet.$scope;
              // Do stuff with $scope.
          }
      });
      
      app.controller('myController',function($scope,myFactory){
      
          myFactory.$scope = $scope;
          /*
              We could just pass $scope as a parameter to foo, but this is
              for cases where for whatever reason, you cannot do this.
          */
          myFactory.foo();
      
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多