【问题标题】:(Angularjs) How to $http.get data and store it in service(Angularjs)如何 $http.get 数据并将其存储在服务中
【发布时间】:2014-02-22 00:35:18
【问题描述】:

正如你将看到的,我在 AngularJS、JS 和 Web 开发方面都是新手 =) 对此我感到非常抱歉,但我会尝试这样做。

我尝试使用 AngularJS 控制器构建一个庞大的网络表单(大约 200 个不同的字段)。我需要从控制器访问根数据源。 AngularJS 团队要求不要仅仅为存储数据提供服务,但我想为加载和保存数据提供服务(在服务器上的 .json 文件中开始)。

服务:

AppName.factory('MasterData', ['$rootScope', '$http', '$q', '$log', 
    function($rootScope, $http, $q, $log) {

    var responseData;
    $http.get('/getdata.php').then(function (response) {
        responseData = response.data;
        console.log(response.data);
    });

    return responseData;

}]);

控制器:

AppName.controller('justController', ['$scope', 'MasterData', '$log',
    function ($scope, MasterData, $log) {
        $scope.data = MasterData.justControllerSectionData;
        console.log(MasterData);
    }
]);

控制器返回未定义。但是来自服务的 console.log 会返回该对象。 我觉得问题太简单了,但我找不到解决方法:( 此外,我不能使用从控制器到服务的 .getData() 之类的功能,因为每次加载任何控制器时它都会从服务器询问数据。我在 AngularJS 应用程序中有 12-14 个控制器的路由(完整的网络表单按部分划分),我认为从后端获取数据一次是件好事。

附:我认为承诺存在问题,但是当我尝试使用这样的代码时:

var defer = $q.defer();
$http.get('/getdata.php').success(function(data){
    defer.resolve(data);
});
return defer;

我有解决、拒绝等的对象。真的不明白我能用它做什么:(

帮我获取控制器中的数据:)

【问题讨论】:

  • 包含 200 个字段的表单?使用Meteor and autoform: {{> quickForm collection="Books" id="insertBookForm" type="insert"}} 可能会更好

标签: javascript json angularjs


【解决方案1】:

您的代码不起作用,因为您在服务中提供给success() 的回调是异步调用的;在您的服务返回后,即:

顺序是这样的:

  1. MasterData 中的function 运行。 $http.get 请求被启动并附加了 promise 回调。 responseData 在此回调中被引用(又名“关闭”)。
  2. 该函数从服务返回到您的控制器。 responseData 尚未设置,不会阻止父作用域函数返回。
  3. $http.get 成功,responseData 已在服务中设置,但控制器无法访问。

如果您不清楚 success() 中嵌套函数的作用域,我建议您阅读 JavaScript 中的闭包(一般情况下甚至更好),例如 here。

您可以通过这样的服务实现您的目标:

function($q, $http, /* ... */) {    
    return {
        getData: function() {
            var defer = $q.defer();
            $http.get('/getdata.php', { cache: 'true'})
            .then(function(response) {
                defer.resolve(response);
            });

            return defer.promise;
    };
}

$http 服务会愉快地缓存您的响应数据,因此您不必这样做。请注意,您需要从您的 deferred 对象中检索 Promise 才能使其正常工作。

控制器是这样的:

/* omitted */ function($scope, YourService) {
    YourService.getData().then(function(response) {
        $scope.data = response.data;
    });
}

由于成功是贬值的,所以我将成功修改为那时。

【讨论】:

  • 我会阅读更多关于 JS 的内容,谢谢你的链接。您的代码使用 than、catch 和 finally 方法返回对象,我应该怎么做才能获取数据:)?
  • 傻我,添加到答案中:)。
【解决方案2】:

服务应该返回承诺而不是数据。这是异步方式。

首先在 Angular 的 run 方法中获取值。对于这个示例,我将它放在 $rootScope 中,因为这使得它可以被所有控制器中的所有范围访问。

AppName.run(['$http', '$rootScope',
    function($http, $rootScope) {
      console.log('Run');
      $http.get('http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo')
        .success(function(data) {
          $rootScope.resource = data;
          console.log($rootScope.resource);
        });
    }
  ])

除非你把它存放在某个奇怪的地方,否则这并不是真正需要的。

AppName.service('Resource',['$rootScope',
    function($rootScope) {
      return $rootScope.resource;
    }
  ]);

每个作用域都将继承 $rootScope 中的值(这就是为什么服务真的没有必要。

AppName.controller('mainController', ['$scope', 'Resource',
  function($scope, Resource) {
    console.log('controller');
    console.log(Resource);
  }
]);

警告!!!在第一个控制器加载之前,此值将不可用。如果您在控制器中使用它,请记住您可以将其绑定到 html,但第一次通过控制器代码时还没有初始化变量。

【讨论】:

  • 如果我是正确的,你的解决方案将在每次控制器加载时运行 $http.get,所以如果我前进到另一个控制器然后回到这个控制器 - 我将运行 $http.get。我需要获取一次数据并将其存储在服务中。
  • 是的,没错。要只运行一次,请在 module.run() 中调用它并将值存储在 module.value() 函数中;
  • 是的,你刚刚忘记了,我有 12 个控制器使用来自 /getdata.php 的数据,每个控制器都在 Angular 中自己的 $route 上使用。如果我将数据存储在一个控制器中,我将不会在另一个控制器中获取数据。所以我需要这项服务。可能是我在 Angular 应用中的逻辑不好?
  • 看看这个 plunker:plnkr.co/edit/aIMMoBd78hqTvtPeL2Nx?p=preview 我会更新我的答案来解决你的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-12
相关资源
最近更新 更多