制作AngularJS服务并使用promise

时间:2014-07-02 16:26:16

标签: angularjs promise

我想创建一个加载JSON文件的服务,并提供一些处理结果的方法。

Blog.service('ArticleService', ['$http', function ($http) {
    this.loadArticles = function() {
        return $http.get('data/articles.json');
    };

    this.getArticles = function () {
        // return the json
    };

    this.getArticle = function (id) {
        // work with the json
    };
}]);

控制器:

Blog.controller('BlogController', function ($scope, ArticleService) {
    console.log(ArticleService.getArticles());

    console.log(ArticleService.getArticle(1));
});

我想缓存请求的结果,然后在我的方法getArticlesgetArticle中使用此结果。

4 个答案:

答案 0 :(得分:1)

根据您的评论,如果您只想做一个请求,那么我建议您在服务中的变量中保存$ http承诺,并在getArticles中返回该变量。

Blog.service('ArticleService', ['$http', function ($http) {
    this.loadArticles = function() {
        return $http.get('data/articles.json');
    };

    var articles;
    this.getArticles = function () {
        if (!articles) {
            articles = this.loadArticles();
        }
        return articles;
    };

    this.getArticle = function (id) {
        // work with the json
    };

}]);

或者更好的是,在init上加载articles变量:

Blog.service('ArticleService', ['$http' '$q', function ($http, $q) {

    var articles = (function() {
        return $http.get('data/articles.json');
    })();

    this.getArticles = function () {
        return articles;
    };

    this.getArticle = function (id) {
        // Return a promise that will be resolved with the correct article.
        var deferred = $q.defer();
        articles.then(function (arts) {
            arts.forEach(function (art) {
                if (art.id === id) {
                    deferred.resolve(art);
                }
            });
        });
        return deferred.promise;  
    };

}]);

Angular曾用于解开承诺,但这被弃用,因为它被证明是麻烦而且非常“神奇”(导致误解)。见https://github.com/angular/angular.js/issues/5153

答案 1 :(得分:1)

或者,您可以使用$http的缓存属性:

Blog.service('ArticleService', ['$http', function ($http) { 

  this.getArticles = function() {
    return $http.get('data/articles.json', {cache: 'myCache'});
  };

  this.getArticle = function (id) {
    return $http.get('data/articles.json', {cache: 'myCache'}).then(function(response) {
       // Parse the response, return the article in question.
    });
  };

}]);

答案 2 :(得分:0)

Blog.service('ArticleService', ['$http', '$q', function ($http, $q)
{
    var self = this;

    this.loadArticles = function ()
    {   

        var deffered = $q.defer();

        $http.get("data/articles.json").then(
                  function (result)
                  {
                      deffered.resolve(result);

                  },
                  function ()
                  {

                      deffered.reject()
                  }

                  );
        return deffered.promise;


    };

    this.getArticles = function ()
    {
        return self.loadArticles;
    };

    this.getArticle = function (id)
    {
        // some stuff to retrieve the object
    };
}]);

然后在您的控制器中

Blog.controller('BlogController', function ($scope, ArticleService)
{
    ArticleService.getArticles().then(function (data)
    {
        console.log(data);
    }, then(function ()
    {
        alert("error")
    })
    );
});

});

答案 3 :(得分:0)

如果您希望缓存在会话期间保持不变,请参阅user3904的答案。

如果缓存可以随页面消亡,那么您可以考虑以下方法:

Blog.service('ArticleService', ['$http', '$q', function ($http, $q) {
    var articles = {};
    var loadArticles = function () {
        articles.multi = $http.get("data/articles.json").done(function(a) {
            articles.multi = a;
        });
        return articles.multi;
    };
    var loadArticle = function (id) {
        articles[id] = $http.get("data/articles.json/" + id).done(function(a) {
            articles[id] = a;
        });
        return articles[id];
    };

    this.getArticles = function () {
        return articles.multi ? $q.when(articles.multi) : loadArticles();
    };
    this.getArticle = function(id) {
        id = '' + id;
        return articles[id] ? $q.when(articles[id]) : loadArticle(id);
    };
}]);

说明

缓存是js普通对象articles

这两个load...()函数是私有的 - 假设它们只能通过相应的get...()函数来调用,这似乎是合理的。 (这对整体解决方案并不特别重要)。

在第一次调用时,两个loadArticles()缓存一个promise,当promise数据到达时,promise将被promise承诺的数据覆盖。承诺暂时缓存有一个原因 - 如果在从服务器返回数据之前发出第二个请求。 $q.when(...)中的this.getArticles()可确保loadArticles()返回包含承诺的数据,无论当前是什么缓存 - 承诺或数据。

this.getArticle()this.getArticles()的工作方式类似,但接受(并传递)了一个ID。

此策略旨在提高存储效率。通过长期缓存数据,避免了promise包装器的(小)开销。如果用户可能在每个会话中请求许多单独的文章,则可能会出现问题。

以高效缓存高效物品的成本为代价购买存储效率。 $q.when(...)需要一些额外的时钟周期才能完成。

使代码适应其他方式应该非常简单 - 即以存储效率为代价优化交付 - 即长期存储承诺并避免需要$q.when(...)

这两种方法都适用,对于大多数应用来说,它采用的是相当优秀的学术方法。