【问题标题】:Angular factory $http get data for multiple pages and global variableAngular factory $http 获取多个页面和全局变量的数据
【发布时间】:2018-12-21 21:39:17
【问题描述】:

我正在使用 Ionic 和 Angular 构建一个简单的应用程序,并且对我的工厂和全局变量有疑问。

我有一个 JSON 文件,其中包含应用程序上每个页面都需要使用的数据。应用中的每个页面也需要访问设备的纬度/经度。

目前,在每个页面的控制器中,我正在调用数据并等待承诺解决,然后再继续处理数据。在每一页上,我还在控制器中为每一页请求经纬度。

这一切似乎有点浪费,因为数据不会在页面之间更改,并且全局设置一次 lat long 似乎是明智的(然后使用 watchPosition 更新它,并在位置更改时使用回调来更新调用的数据)而不必获取位置并将其设置在每个页面 $scope 上。

数据是一个小的 (~20) 位置列表,每个位置都有一个纬度。我想计算每个位置与当前纬度的距离,并随着位置的变化在数据中更新它(来自 watchPosition 的回调)。我的应用有 2 页。一个带有位置列表,另一个在 Google 地图上显示位置。两者都使用相同的数据。

我应该将这些存储在 $rootScope 上还是被认为是不好的做法?我是否以错误的方式思考这个问题?我应该继续目前的道路吗?

目前,我的控制器看起来像:

.....
    .controller('HarboursCtrl', function($scope, Harbours) {

  var harboursPromise = Harbours.all();
  $scope.harbours = [];

  $scope.position = 'Trying to find your location...'

  if (navigator.geolocation){
    navigator.geolocation.getCurrentPosition(function(position){
      $scope.$apply(function(){
        $scope.position = position.coords.latitude+", "+position.coords.longitude;
      })
    })
  } else {
    $scope.position = "Sorry, we can't get your location";
  }

  harboursPromise.then(function(response){
    console.log('response from controller', response);
    $scope.harbours = response.harbours;  
  });
  // $scope.harbours = Harbours.all();

  $scope.remove = function(harbour) {
    Harbours.remove(harbour);
  };
  $scope.getTimes=function(n){
    return new Array(n);
  };
})


.controller('MapCtrl', function($scope, Harbours) {
  $scope.position = 'Trying to find your location...'

  if (navigator.geolocation){
    navigator.geolocation.getCurrentPosition(function(position){
      $scope.$apply(function(){
        $scope.position = position.coords.latitude+", "+position.coords.longitude;
      })
    })
  } else {
    $scope.position = "Sorry, we can't get your location";
  }

  var harboursPromise = Harbours.all();

  harboursPromise.then(function(response){
    console.log('response from controller', response);
    $scope.map = { center: { latitude: 51, longitude: 0 }, zoom: 10 };
    $scope.harbours = [];
    $scope.harbours = response.harbours;  
    console.log($scope.map.harbours);
  });

    });
.....

我的服务看起来像:

angular.module('starter.services', [])

.factory('Harbours', function($http, $q) {
  var harbours = function () {
    var deferred = $q.defer();
    $http({
      method: 'GET',
      url: '../data/harbourData.json'
    }).success(function (data, status, headers, config) {
      deferred.resolve(data);
    }).error(function(data, status, headers, config) {
      deferred.reject(status);
    });
    return deferred.promise;
  }
  return {
    all: harbours,
    get: function(chatId) {
      for (var i = 0; i < harbours.length; i++) {
        if (harbours[i].id === parseInt(chatId)) {
          return harbours[i];
        }
      }
      return null;
    }
  };
});

【问题讨论】:

  • 为什么是$rootScope?您可以使用工厂或服务在控制器和服务之间共享数据。
  • @MudasserAjaz Rootscope 只是我最初的想法。我仍然是一个角处女,还不知道最佳实践,所以寻求建议。干杯
  • 可以为 $http 请求设置cache:true -- 或者-- 如果使用 ui-router 可以在应用程序路由的顶层进行一次解析,它将适用于所有后代状态

标签: angularjs ionic-framework


【解决方案1】:

您的数据是静态的吗?如果是这样,最好写一个常量而不是使用 $http/$q。

angular.module('myModule')
    .constant('locations', {
        firstItem: {
            lat: 'someValue',
            long: 'someValue'
        },
        etc: {}
    });

因此您不必每次都打电话。如果数据是动态的,您始终可以像这样将值缓存在工厂中:

.factory('myFactory', ['$http', '$q', function($http, $q) {
    var harbors = /* resolved object with data */;
    return {
        all: harbors,
        get: function(name) { return harbors[name]; }
    };
});

tldr;工厂是单例的,因此缓存在其中的任何数据都应该可以在应用程序的任何地方使用,而无需调用 $http 服务。

* 编辑 *

我可能会采用的方法是创建一个单独的工厂来缓存我需要重用的任何数据,并编写一个 API 工厂来帮助缓存它。所以,

.factory('appData', [function() {
    var cache = {};

    return {
        set: function(location, payload) {
            cache[location] = payload;
        },
        get: function(location) {
            return cache[location];
        },
        reset: function() {
            cache = {};
        }
    };
}])
.factory('callAPI', ['$http', '$q', 'appData', function($http, $q, appData) {
    return {
        endpoint: function(url, payload, method, cache) {
            var deferred = $q.defer();
            $http({
                method: method,
                url: url
            }).success(function(data, status, headers, config) {
                deferred.resolve(data);
            }).success(function(data, status, headers, config) {
                deferred.reject(status);
            });
            /** cache must be a string */
            appData.set(cache, deferred.promise);
            return deferred.promise;
        }
    }
}])

这也保持了应用程序中关注点的分离。

【讨论】:

  • 最终,数据将由 API 提供,因此更可取的是对其进行缓存。如果可能的话,你能否展示我如何在我的工厂示例中缓存我的数据,然后在控制器中访问它? (感谢这是一个大问题)
  • 好的,我用我可能会如何处理它来更新我的答案。您也可以使用 appData 工厂的相同模式,但首先检查 appData[cache] 是否存在,如果存在,则获取数据,如果不存在,则发出请求。有无数种方法可以做到这一点。
猜你喜欢
  • 2011-01-14
  • 2014-06-22
  • 1970-01-01
  • 2023-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多