从 Angular 服务使用 $http 一次

Use $http once from Angular Service

我需要通过 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(),但它似乎并不适用。

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

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

希望对您有所帮助!

我会说将数据存储在本地(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;
}])

// 缓存数据工厂

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

编辑:同时从控制器中删除 fetchPlaylistItems 并将其放入工厂。控制器只是您的视图模型和视图之间的粘合剂。将所有业务逻辑、http 调用放在一个服务中。

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

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