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

时间:2016-03-15 21:45:44

标签: javascript angularjs

我有一个由一些控制器调用的工厂。

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

现在我想从常规函数调用它并从工厂返回数据。我怎样才能做到这一点?这个不起作用,因为传入的fileData在没有$ scope的情况下无法识别。

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

知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

您对工厂中公开的方法的调用(get)使用返回承诺的$http服务。因此,您无法以同步方式获得此调用的结果。

在您的示例中,return rels在调用handleSuccess方法之前发生,因此您将返回旧值(空数组)。

它在控制器功能内部工作的原因是控制器实例存活的时间较长,当服务器调用成功返回时,控制器的$scope中的变量被分配(然后反映在您的UI通过角度数据绑定)。

因此,解决此问题的最佳方法是避免在“常规函数”中使用同步api。你可以通过返回一个承诺来使这也变得异步吗?

答案 1 :(得分:0)

return rels内移动handleSuccess,您将在handleSuccess被调用之前返回。所以你发信号表示该功能过早地完成了执行。

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);
}

由于您从$http返回了承诺,因此您需要以异步方式处理其执行,直到承诺得到解决后才会返回。

添加reject处理程序也是一个好主意。

Additionally, .success() is deprecated and you should use .then() and .catch() respectively for handling resolve() and reject() of the Promise appropriately.

请参阅下文,了解使用$http

的Promises的首选方法
fileData.get(file)
  .then(handleSuccess)
  .catch(handleFailure); // Handle any errors returned from $http

编辑更新控制器的DI示例

您需要将fileData工厂注入Angular Controller。有关依赖注入的更多信息,请参阅Angular Docs for DI。需要注意的是,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);
    }
  }]);