When I tried this code exactly, I got functions undefined. So I moved implementation on the top and the var service at the bottom and it worked. I also had to declare var metaData at the very top in the code before function declarations.
In any case, after I made that change (e.g. used one service variable instead of return of anonymous object with all function definitions) I still got the same behavior as before.
>That approach works - I use it all the time to cache data. if it doesn't you likely have a logic error somewhere in determining whether the data is already present or you're not storing the data properly in a persistent place where it survives.
>
>Your service looks wrong in a number of ways - I don't know how you're accessing it but you wouldn't be able to even call your getMetaData function on the service since its private.
>
>This is how I would set this up:
>
>
>app.factory('invoicesService', ['$http', '$q', function($http, $q) {
>
> // Interface
> var service = {
> metaData: null,
> getMetaData: getMetaData
> }
> return service;
>
> // Implementation
>
> function getMetaData() {
> var deferred = $q.defer();
>
> if (service.metaData)
> deferred.resolve(service.metaData);
> else {
> $http.get('/api/invoices/metadata')
> .success(function (data) {
> service.metaData = data;
> deferred.resolve(data);
>
> })
> .error(function (data, status, header, config) {
> deferred.reject(status);
> });
> }
> return deferred.promise;
> };
>
>}
>
>
>You don't have to make the metaData public, but my guess is that's what you actually want so it stays accessible and updateable by external code.
>
>+++ Rick ---
>
>>Nice article. We use the first approach in our code.
>>
>>I tried what you suggested (e.g. my new code is
>>
>>
>>app.factory('invoicesService', ['$http', '$q', function($http, $q) {
>>
>> var metaData = null;
>>
>> var getMetaData = function () {
>> var deferred = $q.defer();
>>
>> if (angular.isObject(metaData))
>> deferred.resolve(metaData);
>> else {
>> $http.get('/api/invoices/metadata')
>> .success(function (data) {
>> metaData = data;
>> deferred.resolve(data);
>>
>> })
>> .error(function (data, status, header, config) {
>> deferred.reject(status);
>> });
>> }
>> return deferred.promise;
>> };
>>
>>but I still got hit of my API controller's method twice. I'm going to look into Viv's idea now.
>>
>>>You need to return a promise even if you return the cached data.
>>>
>>>So define your deferred at the top of the code then to return the cached data:
>>>
>>>
>>>if (angular.isObject(metaData)) {
>>> deferred.resolve(metaData);
>>> return deferred.promise;
>>>}
>>>
>>>
>>>This way you get the same data back regardless of whether the data was returned from the AJAX call or from the cached data.
>>>
>>>You might want to read this:
>>>
http://weblog.west-wind.com/posts/2014/Oct/24/AngularJs-and-Promises-with-the-http-Service>>>
>>>which explains some of the mechanics behind this...
>>>
>>>+++ Rick ---
>>>>
>>>
>>>
>>>Define your $q.defer() before the first call then deferred.resolve(metaData); return deferred.promise() with the cached data and return the promise in the if block.
>>>
>>>+++ Rick ---
>>>
>>>>Hi everybody,
>>>>
>>>>I have two pages in the same form that need to access the same data.
>>>>
>>>>Each of the pages is controlled by its own controller and both have this code in the init:
>>>>
>>>>
>>>>invoicesService.getMetaData().then(function (data) {
>>>> $scope.invoicesMetaData = data;
>>>>
>>>> });
>>>>
>>>>So, I want to somehow adjust the service code to not invoke the method twice. Here is what I attempted to do but it's not working:
>>>>
>>>>
>>>>app.factory('invoicesService', ['$http', '$q', function($http, $q) {
>>>>
>>>> var metaData = null;
>>>>
>>>> var getMetaData = function () {
>>>> if (angular.isObject(metaData))
>>>> return metaData;
>>>>
>>>> var deferred = $q.defer();
>>>> $http.get('/api/invoices/metadata')
>>>> .success(function (data) {
>>>> metaData = data;
>>>> deferred.resolve(data);
>>>>
>>>> })
>>>> .error(function (data, status, header, config) {
>>>> deferred.reject(status);
>>>> });
>>>> return deferred.promise;
>>>> };
>>>>
>>>>I still get 2 hits in my API controller. Do you see how should I change the above to avoid the second call after the first one was already made?
>>>>
>>>>Thanks in advance.
If it's not broken, fix it until it is.
My Blog