提供AngularJS服务并与promise合作
我想创建一个加载JSON文件的服务,并提供一些处理结果的方法提供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
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调用完成的唯一方法是使用承诺。请参阅我的最新答案。