diff --git a/angular-widget.js b/angular-widget.js
index 807930fd..4e4a8e75 100644
--- a/angular-widget.js
+++ b/angular-widget.js
@@ -231,7 +231,7 @@ angular.module("angularWidgetInternal").directive("ngWidget", [ "$http", "$templ
angular.module("angularWidgetInternal").value("headElement", document.getElementsByTagName("head")[0]).factory("requirejs", function() {
return window.requirejs || null;
}).value("navigator", navigator).factory("tagAppender", [ "$q", "$rootScope", "headElement", "$interval", "navigator", "$document", "requirejs", "$browser", function($q, $rootScope, headElement, $interval, navigator, $document, requirejs, $browser) {
- var requireCache = [];
+ var requireCache = {};
var styleSheets = $document[0].styleSheets;
function noprotocol(url) {
return url.replace(/^.*:\/\//, "//");
@@ -252,10 +252,10 @@ angular.module("angularWidgetInternal").value("headElement", document.getElement
});
return deferred.promise;
}
- if (requireCache.indexOf(url) !== -1) {
- deferred.resolve();
- return deferred.promise;
+ if (url in requireCache) {
+ return requireCache[url];
}
+ requireCache[url] = deferred.promise;
var fileref;
if (filetype === "css") {
fileref = angular.element("")[0];
@@ -271,6 +271,7 @@ angular.module("angularWidgetInternal").value("headElement", document.getElement
headElement.appendChild(fileref);
fileref.onerror = function() {
fileref.onerror = fileref.onload = fileref.onreadystatechange = null;
+ delete requireCache[url];
if ($rootScope.$$phase) {
deferred.reject();
} else {
@@ -283,7 +284,6 @@ angular.module("angularWidgetInternal").value("headElement", document.getElement
if (!done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete")) {
done = true;
fileref.onerror = fileref.onload = fileref.onreadystatechange = null;
- requireCache.push(url);
if ($rootScope.$$phase) {
deferred.resolve();
} else {
diff --git a/app/scripts/services/tag-appender.js b/app/scripts/services/tag-appender.js
index 79b27e4d..050f3a57 100644
--- a/app/scripts/services/tag-appender.js
+++ b/app/scripts/services/tag-appender.js
@@ -8,7 +8,7 @@ angular.module('angularWidgetInternal')
})
.value('navigator', navigator)
.factory('tagAppender', function ($q, $rootScope, headElement, $interval, navigator, $document, requirejs, $browser) {
- var requireCache = [];
+ var requireCache = {};
var styleSheets = $document[0].styleSheets;
function noprotocol(url) {
@@ -31,10 +31,10 @@ angular.module('angularWidgetInternal')
});
return deferred.promise;
}
- if (requireCache.indexOf(url) !== -1) {
- deferred.resolve();
- return deferred.promise;
+ if (url in requireCache) {
+ return requireCache[url];
}
+ requireCache[url] = deferred.promise;
var fileref;
if (filetype === 'css') {
@@ -52,7 +52,7 @@ angular.module('angularWidgetInternal')
headElement.appendChild(fileref);
fileref.onerror = function () {
fileref.onerror = fileref.onload = fileref.onreadystatechange = null;
-
+ delete requireCache[url];
//the $$phase test is required due to $interval mock, should be removed when $interval is fixed
if ($rootScope.$$phase) {
deferred.reject();
@@ -66,7 +66,6 @@ angular.module('angularWidgetInternal')
if (!done && (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete')) {
done = true;
fileref.onerror = fileref.onload = fileref.onreadystatechange = null;
- requireCache.push(url);
//the $$phase test is required due to $interval mock, should be removed when $interval is fixed
if ($rootScope.$$phase) {
diff --git a/test/spec/services/tag-appender.spec.js b/test/spec/services/tag-appender.spec.js
index 86d19b37..31e15a66 100644
--- a/test/spec/services/tag-appender.spec.js
+++ b/test/spec/services/tag-appender.spec.js
@@ -73,6 +73,24 @@ describe('Unit testing tagAppender service', function () {
.toBe('');
}));
+ it('should return the same promise when same file loads twice simultaneously ', inject (function (tagAppender) {
+ var firstLoadPromise = tagAppender('dummy.js', 'js');
+ var secondLoadPromise = tagAppender('dummy.js', 'js');
+ expect(firstLoadPromise).toEqual(secondLoadPromise);
+ }));
+
+ it('should re try to download the file in case first attempt failed', inject (function (tagAppender) {
+ var secondAttemptSuccess = jasmine.createSpy('secondAttemptSuccess');
+
+ tagAppender('dummy.js', 'js').catch(function () {
+ tagAppender('dummy.js', 'js').then(secondAttemptSuccess);
+ simulateLoadSuccessOnCall(1);
+ });
+
+ simulateLoadErrorOnCall(0);
+ expect(secondAttemptSuccess).toHaveBeenCalled();
+ }));
+
it('should append link tag when css file is added', inject(function (tagAppender) {
tagAppender('dummy.css', 'css');
expect(headElement.appendChild.calls.length).toBe(1);
@@ -198,4 +216,12 @@ describe('Unit testing tagAppender service', function () {
expect(success.calls.length).toBe(1);
}));
+ function simulateLoadSuccessOnCall(callIndex) {
+ headElement.appendChild.calls[callIndex].args[0].onload();
+ }
+
+ function simulateLoadErrorOnCall(callIndex) {
+ headElement.appendChild.calls[callIndex].args[0].onerror();
+ }
+
});