to lo...">

AngularJS Caching Service for inline .svg files (wrapping $ http with promises)

I have applied angular directive <svgimg src="file">

to load .svg images inline, link function uses $ http to download file which is then processed to add and remove tags. The result is inline <svg>

, which can be colored and css sized.

This works great, but since my application will have a lot of small images, this solution is not very efficient because angular calls the service multiple times per digest - this means the download / parsing process is done 100 times ($ http cache helped).

I am trying to replace part of the directive $http.get()

with a caching service.

The cache service maintains a list of already uploaded files and provides a ready-to-use version.

My problem is the implementation of promises ....

Link function app.directive()


link: function( scope, element, attrs ){
    var promise= svgService.get( svgFilename );  // was: $http.get(...)
            // sort injected attribs and then...
        function(data){ /* error stuff */ } 


which seems fine.

The maintenance function is on the lines:

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
            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 :(
                // 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 kind works, but actually loads multiple images (some of them are used multiple times on the page, and the odd one is) I think the problem is that the SOME_PROMISE released in the is loading cache case is not allowed.

I tried to add the object deferred

to the cache and return it to every caller, but it doesn't matter.


I guess I need to keep track of many individual promises ... I need to store the SOME_PROMISE array in the cache and then resolve them all when $ http succeeds?

As a rule, you can only return a copy of this promise to one subscriber?

Any hints / tips / links would be much appreciated ... thanks.


source to share

All Articles