Reputation: 7593
I've just started to learn angularjs and I've literally spent 4 hours on this and I still don't know what's wrong.
I have a service that gets some data from a server.
Service.js
(function() {
"use strict";
angular.module('appName')
.service('MyService', function($http, $q, $location) {
var service = this;
service.data = false;
var deferred = $q.defer();
//makes the api call to get that data
service.load = function() {
$http({
method: 'GET',
url:'/url',
headers: { 'Content-type': 'application/json' },
cache: false
})
.then(function(response) {
service.data = response.data;
deferred.resolve(service.data);
},function() {
deferred.reject("Failed to get data");
});
return deferred.promise;
};
//checks if the data has already been loaded. If not, load it...
service.loaded = function() {
if (!service.data) {
service.load()
.then(function(response) {
deferred.resolve(response);
},
function(response) {
deferred.reject("Failed to load data");
}
);
}
else {
console.log('Already have data');
}
return deferred.promise;
};
//reset the data (for when we log out)
service.destroy = function() {
service.data = false;
};
return {
loaded: service.loaded,
destroy: service.destroy,
getStuff: function () {
return service.data.stuff;
}
};
});
})();
In my controller, I call the service like this
Controller.js
(function() {
"use strict";
angular.module('appName')
.controller('MyController', function($scope, $http, MyService) {
var controller = this;
$scope.stuff = [];
MyService.loaded()
.then(
function(response) {
$scope.stuff = MyService.getStuff();
controller.init();
},
function(response) {
console.log('Error', 'Could not get customers');
});
controller.init = function() {
// do something;
};
});
})();
Here's a little background on my app.
First Screen
User enters username and password and sends query to server. If server returns true, user is redirected to app via $location.url('url');
.
Second Screen
Controller appears on screen, calls Service
. Service
returns data
and Controller
is populated correctly.
So far everything works.
when I click on my logout button, I destroy the data
in the service
.
When I log back in with another username and password, I am still shown the data
from the previous user even though I see in my console that the correct json has been sent by the server. It's as if the service.data
doesn't get updated the second time around. .service
is a singleton... could it be that deferred = $q.defer();
need to be reset?
Please note that if I refresh the browser on my second screen (after a login) I'm shown the correct information.
I appreciate any help.
Upvotes: 1
Views: 58
Reputation: 171690
could it be that deferred = $q.defer(); need to be reset?
Yes, you are only only creating one instance for the life of the app not an instance per api call.
In fact the use of $q
for your $http
calls is totally un-necessary and is considered an ant-pattern.
First lets fix it using $q
so it would work. You need to create a new promise object for every use :
var deferred = $q.defer(); // your one time only object
//makes the api call to get that data
service.load = function() {
Should be:
//makes the api call to get that data
service.load = function() {
// new deferred object each use
var deferred = $q.defer();
However $http
itself returns a promise so all you really need is to return $http
not create a new promise:
service.load = function () {
// return the $http promise
return $http({
method: 'GET',
url: '/url',
headers: {
'Content-type': 'application/json'
},
cache: false
}).then(function (response) {
service.data = response.data;
// instead of `deferred.resolve()` return the data
return service.data
}, function () {
// error handling code
});
};
For your loaded()
method, create a new $q
each time
Upvotes: 1
Reputation: 3456
service.loaded is wrong logic, If loaded create deferred resolve with data, otherwise return load() itself:
service.loaded = function() {
if (service.data) {
var deferred = $q.defer();
deferred.resolve(service.data);
return deferred.promise;
} else {
return service.load();
}
};
I would keep 'var deferred = $q.defer();' separate instances inside each service method, do not share across all service calls.
Upvotes: 1