I have implemented an angular <svgimg src="file">
directive to load .svg images inline, the link function uses $http to load the file which is then parsed to add and remove tags. The result is inline <svg>
which can be coloured and sized with css.
This works fine, but since my app will have loads of small images this solution is not very efficient because angular calls the service multiple times per digest - which means the loading/parsing process is performed 100's of times ($http cache helped).
I am trying to replace the $http.get()
part of the directive with a caching service.
The cache service maintains a list of already-loaded files and provides the ready-to-inject version.
My problem is in implementing the promises....
The app.directive()
link function does:
link: function( scope, element, attrs ){
var promise= svgService.get( svgFilename ); // was: $http.get(...)
promise.then(
function(data){
// sort injected attribs and then...
element.replaceWith(data);
},
function(data){ /* error stuff */ }
);
};
which appears to be fine.
The service function is along the lines of:
app.service('svgCacheService', ['$q', '$http', function($q, $http){
this.get=function( srcfile ){
var deferred= $q.defer();
if( srcfile in cache is loaded ){
deferred.resolve( cache[srcfile] );
return deferred.promise; // ok, no problem with this
}else{
if( srcfile in cache marked as 'loading' ){
// file is marked in cache, but is waiting for $http
return SOME_PROMISE; // tried allsorts, no luck yet :(
}else{
// file not in cache
cache[srcfile]='loading'; // new cache entry, marked 'loading'
$http.get( srcfile )
.success( function(data){
// xml parsing etc. goes in here
cache[srcfile]= data;
// how to resolve waiting promises waiting on 'loading'???
deferred.resolve( cache[srcfile] );
return deferred.promise; // this caller is ok
}
.error( ... error stuff ... )
}
}
}
This sort-of works, but only actually loads a few images (some are used multiple times on a page and the odd one does appear) - I think the problem seems to be that the SOME_PROMISE's issued in the case of 'cache is loading' are not resolved.
I have tried adding the deferred
object in the cache and returning that to each caller, but it makes no difference.
Questions:
I'm guessing that I need to keep track of lots of separate promises... do I need to keep an array of SOME_PROMISE in the cache and then resolve them all when the $http succeeds ?
Generally, can you only return a given promise instance to one caller ?
Any hints/tips/links would be much appreciated... thanks.