zmark
zmark

Reputation: 127

Service or provider with cached data

On a server side I have a json file in a dictionary form:

{
    "term1": "definition1",
    "term2": "definition2",
    "term3": "definition3"
}

I'm trying to create a service or provider (one of them is sufficient) which will have a cache of a data from this json file and will be able to use it.

The structures look like:

myApp.service('translateSrv', function() {
    this.dictionaryData; // how to populate

    this.translate = function(input) {
        return this.dictionaryData[input];
    };
});

myApp.provider('translateProvider', function() {
    this.dictionaryData; // how to populate

    this.$get = function() {
        return {
            translate: function() {
                return this.dictionaryData[input];
            }
        }
    };
});

My question is how to populate a dictionary data in this service or provider before the first call of translate() method (in a time of module creation/configuration)? I can't do it asynchronously while first method call.

I want to use one of this structure, among others, in a filter:

myApp.filter('translate', ['translateProvider', function(translateProvider) {
    return function(input) {
        return translateProvider.translate(input);
    }
}]);

I've started recently my work with Angular so maybe my approach is wrong. I will appreciate every hint.

Upvotes: 1

Views: 159

Answers (1)

atondelier
atondelier

Reputation: 2434

Provider name:

Do not suffix your provider name with 'Provider' since the name you will use to inject the provider in config functions will already be suffixed with 'Provider'

myApp.provider('translate', /*...*/); 
// -> injectable provider is 'translateProvider'
// -> injectable instance is 'translate'


Populate the provider in a config function:

myApp.config(['translateProvider', function(translateProvider) {
    translateProvider.dictionaryData = { /*...*/ };
});


Advice for performance!

  • If your translations are static per page view, please consider pre translating your templates.
  • If you really need it, prefer writing the whole translation js object in an inline script in the document
    • 1 XHR less
    • no lazy loading deferring application load


Lazy loading

If you really have to lazy load those translations:

  • Either defer application loading with an external XHR before application load, while keeping the translationData at the provider configuration level,
  • Or take advantage of the "resolve" part of angular rooting or ui-router, while setting the translationData object on the instance (not on the provider)


How to choose between both?

  • The first option is quite easy and you won't have to couple application routing with your lazy load constraint.
  • For the second choice, prefer ui-router and declare an abstract state responsible for handling the lazy loaded data in the "resolve" state property and make other states be children of this abstract state, so that you won't have to add resolve constraints on each state that have a dependency on translations.

Upvotes: 3

Related Questions