Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
提供AngularJS服务并与promise合作_Angularjs_Promise - Fatal编程技术网

提供AngularJS服务并与promise合作

提供AngularJS服务并与promise合作,angularjs,promise,Angularjs,Promise,我想创建一个加载JSON文件的服务,并提供一些处理结果的方法 Blog.service('ArticleService', ['$http', function ($http) { this.loadArticles = function() { return $http.get('data/articles.json'); }; this.getArticles = function () { // return the json

我想创建一个加载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));
});
我想缓存请求的结果,然后在我的方法中使用该结果,
getArticles
getArticles

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

}))

在您的评论之后,如果您只想执行一个请求,那么我建议您将$http promise保存在服务中的一个变量中,并在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过去常常拆开承诺,但这被弃用,因为事实证明这很麻烦,而且非常“神奇”(导致误解)。请参见

或者,您可以使用
$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.
    });
  };

}]);

如果希望缓存在会话之间保持不变,请参阅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普通对象
文章

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

在第一次调用时,两个
loadArticles()
缓存一个promise,该promise在数据到达时被promise交付的数据覆盖。由于一个原因,承诺被临时缓存——以防在从服务器返回数据之前发出第二个请求。
this.getArticles()
中的
$q.when(…)
确保
loadArticles()
返回承诺包装的数据,而不管当前缓存的是什么-承诺还是数据

this.getArticles()
的工作原理与
this.getArticles()
类似,但接受(并传递)一个id

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

存储效率是以交付缓存项目的效率稍低为代价的<代码>$q。何时(…)将需要一些额外的时钟周期才能完成

将代码调整为另一种方式应该非常简单-即以存储效率为代价优化交付-即长期存储承诺,避免需要
$q.when(…)


这两种方法都会起作用,对于大多数应用来说,采用哪一种方法是相当学术性的

正如@Sylvester在他的回答中所写的那样,如果不在您的服务中创建一个承诺并将该承诺传递给控制器,恐怕您想要什么是不可能的。为什么要缓存结果?HTTP服务器应该告诉您资源是否可缓存,而不是客户端。如果我有3个处理JSON数据的方法,我不想发出3个HTTP请求。实现这一目标的最佳方式是什么?假设我必须多次使用
getArticle(id)
,我不会重复在多个控制器中获取一篇文章的方式。只需将返回的承诺缓存在您的服务中。这取决于OP希望缓存的持久性。javascript中的缓存将在页面的整个生命周期中持续;浏览器缓存将跨越会话。我猜
getArticle()
应该在浏览器缓存中,
getArticles
应该在js中,但只有OP知道。我真的不明白为什么你必须发出两个HTTP请求,因为这是一个异步请求?我的服务方法必须仅在JSON就绪时可用。那么,发出同步请求怎么样?为每个方法生成
$http.get()
似乎很无聊。@sylouuu,如果您使用如上所示的
缓存
配置属性,将不会有两个http请求。首先调用的方法将触发一个请求,随后对任一方法的调用都将使用缓存响应。我的服务只使用一个JSON文件
articles.JSON
。我想在
articles
变量中获取JSON,并在
getArticles()
getArticle(id)
中使用此变量。是的,我知道这就是您想要的。我所提供的上述是一些实际工作
getArticle()
必须使用
getArticles()
,因为我需要在articles中创建一个循环,以提取正确的索引。如何在不执行另一个HTTP请求的情况下实现这一点?干…@sylouuu,好吧,我明白你想要什么,但这不是角度服务和承诺的工作方式。这也不是干的问题。如果在服务工厂函数运行时进行$http服务调用以加载JSON,那么您就有可能在$http调用完成之前调用
getArticle()
getArticles()
。确保ajax调用完成的唯一方法是使用承诺。请参阅我的最新答案。