从Angular Service使用$ http

时间:2015-05-14 20:38:25

标签: angularjs angular-http

我需要通过API从我的数据库中获取一些数据,并在整个Angular应用程序中访问它。我知道服务适用于存储要从多个控制器访问的数据。但是,在下面的代码中,我每次只得到一个新的$ hhtp.get()来获取相同的数据。

服务:

.factory('Playlist', ['$http', function($http) {
  var playlist = {};

  playlist.getPlaylist = function() {
   return $http.get('api/playlist.php')
   .then(function (response) {
     var data = response.data;
     return data;
    })
  }

  return playlist;
}])

控制器:

.controller('ScheduleCtrl', ['$http', 'Playlist', function($http, Playlist) {
  var self = this;

  Playlist.getPlaylist()
  .success(function(playlist) {
    self.playlist_id = playlist.id;
    fetchItems();
  })

  var fetchScheduleItems = function() {
    return $http.get('api/schedule.php/'+self.playlist_id).then(
      function(response) {
        if (response.data === "null") {
          console.log("No items");
        } else {
          self.items = response.data;
        }
      }, function(errResponse) {
        console.error('Error while fetching schedule');
    });
  };
}])
.controller('PlaylistItemCtrl', ['$http', 'Playlist', function($http, Playlist) {
  var self = this;

  Playlist.getPlaylist()
  .success(function(playlist) {
    self.playlist_id = playlist.id;
    fetchItems();
  })

  var fetchPlaylistItems = function() {
    return $http.get('api/schedule.php/'+self.playlist_id).then(
      function(response) {
        if (response.data === "null") {
          console.log("No items");
        } else {
          self.items = response.data;
        }
      }, function(errResponse) {
        console.error('Error while fetching schedule');
    });
  };
}])

有没有办法存储播放列表ID而无需从每个控制器ping“api / playlist.php”?

更新

这是基于Abhi答案的Plunkr:http://plnkr.co/edit/or9kc4MDC2x3GzG2dNeK?p=preview

正如您在控制台中看到的那样,它仍然会多次击中服务器。我试过以不同方式嵌套CachedData.save(),但它似乎不适用。

2 个答案:

答案 0 :(得分:1)

我想说在本地存储您的数据(CachedData工厂 - 将其重命名为有意义的东西)并在您的getPlaylist方法中,在进行http调用之前,检查CachedData以查看您的数据是否存在,如果不存在,则执行http调用

代码将如下所示。我刚刚写了它,所以可能会有一些错误,但你得到了图片。

.factory('Playlist', ['$http', 'CachedData', function($http, CachedData) {
 var playlist = {};

playlist.getPlaylist = function() {
  if (CachedData.data) {
     // return cached data as a resolved promise
  } else 
  return $http.get('api/playlist.php')
    .then(function (response) {
    var data = response.data;
    cachedData.save(data);
    return data;
   })
  }
  return playlist;
}])

// CachedData工厂

.factory('CachedData', function() {
     var _data;
     var cachedData = {
         data: _data,
         save: function(newData) {
             _data = newData;
         }
     };
     return cachedData;
})

编辑:还从控制器中删除fetchPlaylistItems并将其放入工厂。控制器只是viewmodel和view之间的粘合剂。将所有业务逻辑,http调用放入服务中。

编辑:我为你设置了一个插件here。我希望它有所帮助。

编辑:John,你看到两个服务器调用的原因是因为它们来自不同的控制器ManiCtrl1和MainCtrl2。到那时,调用MainCtrl2的getPlaylist方法,第一个http请求没有机会完成并保存数据。如果在调用服务方法之前向MainCtrl2添加超时,您将看到从缓存中检索数据。有关演示,请参阅this updated plunk。 这在具有多个视图的应用中会更有用,您可以在导航回视图时不想重新加载数据。 (理想情况下,根据您缓存的数据类型,您将有一些到期时间,之后您需要重新加载数据)。

答案 1 :(得分:0)

调用该方法时可以进行一些预验证。

  var playlist = {};
  playlist.playlist = [];

  playlist.getPlaylist = function () {
    if (playlist.playlist.length <= 0) { //or some lodash _.isEmpty()
      $http.get('api/playlist.php')
        .then(function (response) {
          playlist.playlist = response.data;
        })
    }
    return playlist.playlist;
  };

希望它有所帮助!