简体   繁体   English

如何从AngularJs中的常规函数​​调用工厂

[英]how to call a factory from a regular function in AngularJs

I have this factory which is called by some controllers. 我有一个被某些控制器称为工厂的工厂。

app.factory('fileData', function($http) { 
    return {
        get:  function(filename){  return $http({ method: 'GET',  url: filename}); 
        }
    };
});

Now I want to call it from a regular function and return the data from the factory. 现在,我想从常规函数中调用它,并从工厂返回数据。 How can I do that? 我怎样才能做到这一点? This one does not work because the fileData passed in is not recognized without $scope. 这是行不通的,因为没有$ scope不能识别传入的fileData。

function getData (file, fileData) {
   rels = [];
   var handleSuccess = function(data, status) {
      rels = data;
      console.log(rels);
   };
   fileData.get(filename).success(handleSuccess);
   return rels;     
}

Any idea how to go around this? 知道如何解决这个问题吗?

Your call to the method exposed in the factory ( get ) uses the $http service which returns a promise. 您对工厂中公开的方法的调用( get )使用$http服务,该服务返回一个承诺。 So you cannot get the result of this call in a synchronous way. 因此,您无法以同步方式获得此调用的结果。

In your sample the return rels happens way before the handleSuccess method is called and thus you are returning the old value (an empty array). 在您的示例中, return rels发生在调用handleSuccess方法之前,因此您将返回旧值(一个空数组)。

The reason it works inside of a controller function is that the controller instance is living for a longer time and when the server call returns successfully, the variable in you controller's $scope is assigned (which then is reflected in your UI via the angular data binding). 它在控制器功能中起作用的原因是控制器实例的生存时间更长,并且当服务器调用成功返回时,将分配控制器$scope的变量(然后通过角度数据绑定将其反映在您的UI中)。

So the best way to solve this, is to avoid having a synchronous api in your "regular function". 因此,解决此问题的最佳方法是避免在“常规函数”中使用同步api。 Could you probably make this also async by returning a promise? 您是否可以通过返回承诺使它也异步?

Move return rels inside handleSuccess , you're returning before handleSuccess is getting called. 移动return relshandleSuccess ,你才返回handleSuccess获取调用。 So you're signaling that the function completed execution prematurely. 因此,您表示该函数过早完成了执行。

function getData (file, fileData) {
   rels = [];
   var handleSuccess = function(data, status) {
      rels = data;
      console.log(rels);

      return rels; // Return rels when the Promise is finished
   };

   fileData.get(file).success(handleSuccess);
}

Since you're returning the promise from $http , you need to handle its execution in an asynchronous way which, is simply not returning until the promise is resolved. 由于您要从$http返回承诺,因此您需要以异步方式处理其执行,直到承诺被解决后才返回。

It would also be a good idea to add a reject handler. 添加reject处理程序也是一个好主意。

Additionally, .success() is deprecated and you should use .then() and .catch() respectively for handling resolve() and reject() of the Promise appropriately. 此外, .success()已被废弃,你应该使用.then().catch()分别用于处理resolve()reject()适当的承诺。

See below for the preferred approach to Promises with $http 参见下文,了解使用$http进行承诺的首选方法

fileData.get(file)
  .then(handleSuccess)
  .catch(handleFailure); // Handle any errors returned from $http

EDIT Update for DI example for controller 控制器的DI示例的EDIT更新

You need to inject the fileData factory into your Angular Controller. 您需要将fileData工厂注入到Angular Controller中。 For more info on Dependency Inject see the Angular Docs for DI . 有关Dependency Inject的更多信息,请参见DIAngular文档 Just to note, DI is a huge piece of Angular so it is pretty fundamental to understand this before proceeding. 请注意,DI是Angular的重要组成部分,因此在继续进行之前了解这一点非常基础。

angular
  .module('yourApp')
  .controller('yourController', ['$scope', 'fileData', function($scope, fileData) {
    // Expose getData via $scope
    $scope.getData = getData;

    function getData(file, fileData) {
      var rels = [];
      var handleSuccess = function(data, status) {
        rels = data;
        console.log(rels);
        return rels;   
      };

      fileData.get(file)
        .then(handleSuccess);
    }
  }]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM