Temporarily store promises until they are resolved

The original commit simply stored promises into the cache,
which seemed to work in browsers but failed with karma/PhantomJS.

I'm not yet certain why that is, but I wanted to get rid of complex
objects in sessionStorage anyway, so this commit does:

* temporarily store running promises for a given key
* cache the resolved data directly
pull/3553/head
Oliver Günther 9 years ago
parent 64d5b399c5
commit d3d6cd60ee
  1. 6
      frontend/app/openproject-app.js
  2. 38
      frontend/app/services/cache-service.js
  3. 3
      frontend/app/work_packages/activities/user-activity-directive.js
  4. 64
      frontend/tests/unit/tests/work_packages/activities/user-activity-directive-test.js

@ -74,7 +74,8 @@ angular.module(
'openproject.uiComponents', 'openproject.uiComponents',
'openproject.helpers', 'openproject.helpers',
'openproject.workPackages.config', 'openproject.workPackages.config',
'openproject.workPackages.helpers' 'openproject.workPackages.helpers',
'angular-cache'
]); ]);
angular.module('openproject.helpers', ['openproject.services']); angular.module('openproject.helpers', ['openproject.services']);
angular angular
@ -191,8 +192,7 @@ var openprojectApp = angular.module('openproject', [
'cgBusy', 'cgBusy',
'openproject.api', 'openproject.api',
'openproject.templates', 'openproject.templates',
'monospaced.elastic', 'monospaced.elastic'
'angular-cache'
]); ]);
window.appBasePath = jQuery('meta[name=app_base_path]').attr('content') || window.appBasePath = jQuery('meta[name=app_base_path]').attr('content') ||

@ -32,11 +32,16 @@ module.exports = function(
$q, $q,
CacheFactory) { CacheFactory) {
var cacheName = 'openproject-cache'; var cacheName = 'openproject-cache',
var _cache = CacheFactory(cacheName, { _promises = {},
maxAge: 30 * 60 * 1000, // 30 mins _cache = CacheFactory.get(cacheName);
storageMode: 'sessionStorage'
}); if (!_cache) {
_cache = CacheFactory(cacheName, {
maxAge: 10 * 60 * 1000, // 10 mins
storageMode: 'sessionStorage',
});
}
var CacheService = { var CacheService = {
@ -48,29 +53,40 @@ module.exports = function(
return _cache.get(key); return _cache.get(key);
}, },
remove: function(key) {
_cache.remove(key);
},
loadResource: function(resource, force) { loadResource: function(resource, force) {
var deferred = $q.defer(), var deferred = $q.defer(),
key = resource.props.href, key = resource.props.href,
cached = CacheService.get(key); cached = CacheService.get(key);
// Got the result directly? Great.
if (cached && !force) {
deferred.resolve(cached);
}
// Return an existing promise if it exists // Return an existing promise if it exists
// Avoids intermittent requests while a first // Avoids intermittent requests while a first
// is already underway. // is already underway.
if (cached && !force) { if (_promises[key]) {
return cached; return _promises[key];
} }
var promise = deferred.promise;
CacheService.cache(key, promise);
resource.fetch().then(function(data) { resource.fetch().then(function(data) {
CacheService.cache(key, data);
deferred.resolve(data); deferred.resolve(data);
}, function() { }, function() {
deferred.reject(); deferred.reject();
CacheService.remove(key);
}); });
var promise = deferred.promise;
_promises[key] = promise;
return promise; return promise;
}, }
}; };
return CacheService; return CacheService;

@ -75,7 +75,8 @@ module.exports = function($uiViewScroll,
scope.userCanQuote = !!scope.workPackage.links.addComment; scope.userCanQuote = !!scope.workPackage.links.addComment;
scope.accessibilityModeEnabled = ConfigurationService.accessibilityModeEnabled(); scope.accessibilityModeEnabled = ConfigurationService.accessibilityModeEnabled();
UserService.getUserByResource(scope.activity.links.user).then(function(user) { var resource = UserService.getUserByResource(scope.activity.links.user);
resource.then(function(user) {
scope.userId = user.props.id; scope.userId = user.props.id;
scope.userName = user.props.name; scope.userName = user.props.name;
scope.userAvatar = user.props.avatar; scope.userAvatar = user.props.avatar;

@ -47,7 +47,7 @@ describe('userActivity Directive', function() {
}); });
}); });
beforeEach(inject(function($rootScope, $compile, $uiViewScroll, $timeout, $location, I18n, PathHelper, ActivityService, UsersHelper) { beforeEach(inject(function($rootScope, $compile, $uiViewScroll, $timeout, $location, I18n, PathHelper, ActivityService, UsersHelper, UserService) {
var html; var html;
html = '<user-activity work-package="workPackage" activity="activity" activity-no="activityNo" is-initial="isInitial" input-element-id="inputElementId"></user-activity>'; html = '<user-activity work-package="workPackage" activity="activity" activity-no="activityNo" is-initial="isInitial" input-element-id="inputElementId"></user-activity>';
@ -74,21 +74,20 @@ describe('userActivity Directive', function() {
}; };
scope.activity = { scope.activity = {
links: { links: {
update: true,
user: { user: {
props: { href: '/api/v3/users/1' },
fetch: function() { fetch: function() {
return { var deferred = $q.defer();
then: function(cb) { deferred.resolve({
cb({ props: {
props: { id: 1,
id: 1, name: "John Doe",
name: "John Doe", avatar: 'avatar.png',
avatar: 'avatar.png', status: 1
status: 1 }
} });
}
);} return deferred.promise;
};
} }
} }
}, },
@ -114,7 +113,7 @@ describe('userActivity Directive', function() {
}; };
scope.isInitial = false; scope.isInitial = false;
compile(); compile();
}); }));
context("user's avatar", function() { context("user's avatar", function() {
it('should have an alt attribute', function() { it('should have an alt attribute', function() {
@ -126,23 +125,28 @@ describe('userActivity Directive', function() {
}); });
describe('when being empty', function() { describe('when being empty', function() {
beforeEach(function() { beforeEach(inject(function($q) {
scope.activity.links.user.fetch = function() { scope.activity.links.user = {
return { props: {
then: function(cb) { href: '/api/v3/users/2'
cb({ },
props: { fetch: function() {
id: 1, var deferred = $q.defer();
name: "John Doe", deferred.resolve({
avatar: '', props: {
status: 1 id: 2,
} name: "John Doe",
}); avatar: '',
} status: 1
}; }
});
return deferred.promise;
}
}; };
compile(); compile();
}); }));
it('should not be rendered', function() { it('should not be rendered', function() {
expect(element.find('.avatar')).to.have.length(0); expect(element.find('.avatar')).to.have.length(0);

Loading…
Cancel
Save