【问题标题】:AngularJS : Access stored data in a factory after a $http callAngularJS:在 $http 调用后访问工厂中存储的数据
【发布时间】:2014-02-20 09:12:08
【问题描述】:

我正在尝试构建一个工厂来充当我的数据库模型的暂存区,以及一个用于执行基本 CRUD 调用的 api。我希望能够通过将数据存储在服务或工厂中来访问数据,并保留 api 方法,以便我可以在控制器中执行类似的操作。

$scope.folders =  Folders.data(); // for a factory
$scope.folders = Folders.data; // for a Service

Folders.create({name: "My Stuff, $oid: { 5fwewe033333 }, user_id: CurrentUser.id"});

目前我在控制器中使用这样的文件夹工厂。

Folders.foldersData().success( function(data, status) {
   $scope.folder = data;
})
.error( function(data,status) {
   Flash.warning("There was a problem fetching your data");
});

我知道我可以在控制器中解决一个承诺,但是鉴于我正在处理的项目的大小,我喜欢在服务中访问文件夹模型的想法,而不必进行服务器调用每次我进行更改时同步数据。

angular.module('cmsApp')
  .factory('Folders', function($http, $q){

    var folders = {};
    var messageWarn = "Upload Retrival Failed.";


    return {
      get: function(){
        var defered = $q.defer();

        $http.get('/folders').success( function ( data, status ) {
          defered.resolve(data);
        })
        .error( function ( data, status ) {
          defered.reject();
          Flash.warning(message_warn);
        });
        defered.promise.then( function (promise)
          folders = promise;
        });
      }, 
      data: function (){
      return folders;
    },
  }               
});

我的问题是我无法在调用 Folders.get() 后保留文件夹对象。在我将 Folders.data() 作为空对象调用后,它总是会回来。

有没有办法将这些数据保存在工厂中,作为文件夹模型的最新表示,而不依赖于每次都访问服务器?

在 Rails 4 API 上运行 Angular 1.2.3。

【问题讨论】:

  • 是的,我举个例子。我认为您感到困惑的主要是工厂创建服务然后完成。可以这么说,您无法访问工厂。仅限服务。

标签: javascript angularjs angularjs-scope angularjs-service angularjs-factory


【解决方案1】:

在本例中,服务本质上是IS数据。第一次注入服务时,会创建一个 Promise,然后调用就会结束。该服务实际上是该数据的承诺,但是当调用返回时,该承诺与数据一起解决。因此,在第二次、第三次等注入服务时,不再进行调用 - 工厂已经完成了它的工作并返回了服务(本例中的承诺)。

Live demo (click).

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope, myService) {
  myService.then(function(data) {
    $scope.data = data
  })
});

app.factory('myService', function($http, $q) {
  //this runs the first time the service is injected
  //this creates the service

  var promise = $http.get('my-file.json').then(function(resp) {
    return resp.data;
  });

  return promise;

});

这是一个 expanded demo,我在其中使用了两次数据。请注意控制台日志 - 调用只进行一次。在这个演示中,我使用返回承诺的get 方法将服务变成了一个对象。我只是想演示另一种实现这种技术的方式。

app.factory('myService', function($http, $q) {

  console.log('Making the call!');
  var promise = $http.get('my-file.json').then(function(resp) {
    return resp.data;
  });

  var myService = {
    get: function() {
      return promise;
    }
  };

  return myService;
});

【讨论】:

  • 谢谢@m59,但是如果我想将已解决的承诺存储在服务中并能够在不必再次访问服务器的情况下操作数据呢?所以我可以拨打 Folders.data[1] = { folder_name: "New Folder" }
  • 我有同样的问题,我也想在服务中存储已解决的承诺
  • @allencoded 我不确定您遇到了什么问题。我演示了两种可以做到这一点的方法,它们都可以正常工作。
  • 他们保存返回的承诺,但我想保存数据本身。
  • @allencoded 实际上是一样的。你所说的在语义上是行不通的。当然,您可以在呼叫返回时直接将数据应用到服务,但这并不能让您控制数据的使用方式。该数据的消费者最终会在 ajax 调用返回之前尝试使用这些数据。从异步源访问数据时,返回它的承诺是正确的。如果数据已经存在,那就意味着then 函数将立即触发。
【解决方案2】:

您可以将承诺作为服务上的对象存储在服务中。我 fork 上面的扩展演示来演示 http://plnkr.co/edit/2HqQAiD33myyfVP4DWg3?p=preview

与前面的示例一样,http 调用只进行一次,但这次 Promise 被添加到由工厂创建的服务对象上的文件夹项中。


app.factory('myService', function($http, $q) {

  return {

    myObject: '',

    get: function() {
      // Create the deffered object
      var deferred = $q.defer();

      if(!this.myObject) {
        // Request has not been made, so make it
        $http.get('my-file.json').then(function(resp) {
          console.log('Making the call!');
          deferred.resolve(resp.data);
        });
        // Add the promise to myObject
        this.myObject = deferred.promise;
      }
      // Return the myObject stored on the service
      return this.myObject;

    }

  };

});

【讨论】:

  • 我添加了一个额外的 plunkr,演示了一种更有用的方法,使您能够重用请求代码,但每个控制器仍然只发出一次请求。请参阅plnkr.co/edit/2HqQAiD33myyfVP4DWg3?p=preview 就我个人而言,我将 makeRequest 对象封装为具有更大灵活性的自己的服务(例如 HTTP GET、POST、DELETE 等),并将该服务注入到将访问我的 api 的所有其他服务中。
  • 我看不出这与我的回答有何不同。有很多方法可以呈现相同的概念。此外,您通过手动创建一个 Promise 来使用 Promise 反模式,而不是使用 $http 调用返回的 Promise。
  • @aaronroberson 你的链接失效了? :)
  • @AndersMetnik 我的答案和这个答案之间唯一真正的区别是这个答案使用了 Promise 反模式(这很糟糕),而且我更快地获取数据(次要细节 - 易于更改)。我很乐意帮助澄清您不理解的代码。请告诉我。
  • @ 全部。我做了一些研究,似乎这种模式确实是错误的。我希望我能收回我的赞成票。如果有人看到这个,请改用@m59 的回答。它更简单,也更可靠。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-25
  • 2019-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多