javascript 在 AngularJS 服务中缓存承诺对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18744830/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Caching a promise object in AngularJS service
提问by andrew.fox
I want to implement a dynamic loading of a static resource in AngularJS using Promises. The problem: I have couple components on page which might (or not, depends which are displayed, thus dynamic) need to get a static resource from the server. Once loaded, it can be cached for the whole application life.
我想使用 Promises 在 AngularJS 中实现静态资源的动态加载。问题:我在页面上有几个组件可能(或不,取决于显示的内容,因此是动态的)需要从服务器获取静态资源。加载后,它可以在整个应用程序生命周期中缓存。
I have implemented this mechanism, but I'm new to Angular and Promises, and I want to make sure if this is a right solution \ approach.
我已经实现了这个机制,但我是 Angular 和 Promises 的新手,我想确定这是否是一个正确的解决方案\方法。
var data = null;
var deferredLoadData = null;
function loadDataPromise() {
if (deferredLoadData !== null)
return deferredLoadData.promise;
deferredLoadData = $q.defer();
$http.get("data.json").then(function (res) {
data = res.data;
return deferredLoadData.resolve();
}, function (res) {
return deferredLoadData.reject();
});
return deferredLoadData.promise;
}
So, only one request is made, and all next calls to loadDataPromise() get back the first made promise. It seems to work for request that in the progress or one that already finished some time ago.
因此,只发出一个请求,所有对 loadDataPromise() 的下一次调用都会返回第一个做出的承诺。它似乎适用于正在进行的请求或前一段时间已经完成的请求。
But is it a good solution to cache Promises?
但它是缓存 Promise 的好方法吗?
回答by Bergi
Is this the right approach?
这是正确的方法吗?
Yes. The use of memoisationon functions that return promises a common technique to avoid the repeated execution of asynchronous (and usually expensive) tasks. The promise makes the caching easy because one does not need to distinguish between ongoing and finished operations, they're both represented as (the same) promise for the result value.
是的。在返回的函数上使用记忆化保证了一种避免重复执行异步(通常是昂贵的)任务的通用技术。承诺使缓存变得容易,因为不需要区分正在进行的和已完成的操作,它们都表示为结果值的(相同)承诺。
Is this the right solution?
这是正确的解决方案吗?
No. That global data
variable and the resolution with undefined
is not how promises are intended to work. Instead, fulfill the promise with the result data
! It also makes coding a lot easier:
不。那个全局data
变量和解析undefined
不是承诺的工作方式。相反,用结果履行承诺data
!它还使编码更容易:
var dataPromise = null;
function getData() {
if (dataPromise == null)
dataPromise = $http.get("data.json").then(function (res) {
return res.data;
});
return dataPromise;
}
Then, instead of loadDataPromise().then(function() { /* use global */ data })
it is simply getData().then(function(data) { … })
.
然后,而不是loadDataPromise().then(function() { /* use global */ data })
简单地getData().then(function(data) { … })
.
To further improve the pattern, you might want to hide dataPromise
in a closure scope, and notice that you will need a lookup for different promises when getData
takes a parameter (like the url).
为了进一步改进该模式,您可能希望隐藏dataPromise
在一个闭包作用域中,并注意到当getData
接受一个参数(如 url)时,您将需要查找不同的 Promise。
回答by Andzej Maciusovic
For this task I created service called defer-cache-service which removes all this boiler plate code. It writted in Typescript, but you can grab compiled js file. Github source code.
对于这个任务,我创建了一个名为 defer-cache-service 的服务,它删除了所有这些样板代码。它是用 Typescript 编写的,但您可以抓取编译后的 js 文件。Github 源代码。
Example:
例子:
function loadCached() {
return deferCacheService.getDeferred('cacke.key1', function () {
return $http.get("data.json");
});
}
and consume
并消耗
loadCached().then(function(data) {
//...
});
One important thing to notice that if let's say two or more parts calling the the same loadDataPromise and at the same time, you must add this check
需要注意的一件重要事情是,如果让我们说两个或更多部分同时调用相同的 loadDataPromise,则必须添加此检查
if (defer && defer.promise.$$state.status === 0) {
return defer.promise;
}
otherwise you will be doing duplicate calls to backend.
否则你将重复调用后端。
回答by vsync
This design design pattern will cachewhatever is returned the first time it runs , and return the cachedthing every time it's called again.
这种设计设计模式将缓存第一次运行时返回的内容,并在每次再次调用时返回缓存的内容。
const asyncTask = (cache => {
return function(){
// when called first time, put the promise in the "cache" variable
if( !cache ){
cache = new Promise(function(resolve, reject){
setTimeout(() => {
resolve('foo');
}, 2000);
});
}
return cache;
}
})();
asyncTask().then(console.log);
asyncTask().then(console.log);
Explanation:
解释:
Simply wrap your function with another self-invoking function which returns a function (your original async function), and the purpose of wrapper function is to provide encapsulating scope for a local variable cache
, so that local variable is only accessible within the returned function of the wrapper function and has the exact same value every time asyncTask
is called (other than the very first time)
简单地用另一个自调用函数包装你的函数,它返回一个函数(你原来的异步函数),包装函数的目的是为局部变量提供封装范围cache
,这样局部变量只能在返回的函数内访问包装函数并且每次asyncTask
调用时都具有完全相同的值(第一次除外)