Angular JS: Service Response not Saving to Variable - angularjs

I'm trying to work out why the response of this service isn't saving to $scope.counter. I've added a function to my service fetchCustomers(p) which takes some parameters and returns a number, which I'd like to save to $scope.counter.
service
angular.module('app')
.factory('MyService', MyService)
function MyService($http) {
var url = 'URL'';
return {
fetchTotal: function(p) {
return $http.get(url, { params: p })
.then(function(response) {
return response.data.meta.total;
}, function(error) {
console.log("error occured");
})
}
}
}
controller
$scope.counter = MyService.fetchTotal(params).then(function(response) {
console.log(response);
return response;
});
For some reason though, this isn't working. It's console logging the value, but not saving it to $scope.counter. Any ideas?

If I understand your question correctly, you're setting $scope.counter to a promise, not the response.
MyService.fetchTotal(params).then(function(response) {
// Anything dealing with data from the server
// must be put inside this callback
$scope.counter = response;
console.log($scope.counter); // Data from server
});
// Don't do this
console.log($scope.counter); // Undefined

Related

ionic angular data not passing properly

I am retrieving json data form a url, and if i output to console the data is there.. but when i am injecting it to the controller its not working. What did i do wrong?
angular.module('starter.notifications', [])
.factory('Notifications', function($http) {
return {
getAll: function()
{
return $http.get(link).then(function(response){
console.log(response.data);
notifications = response.data;
return notifications;
});
}
}
My controller
.controller('NotificationsCtrl', function($scope, $state, Notifications) {
$scope.notifications = Notifications.getAll();
})
$scope.notifications is null. So i don't understand why thats not working.
UPDATE:
So i now have it passing the data.. but i guess i don't understand how to use it.
Correct/Working code
getAll: function()
{
notifications = ($http.get(link).then(function(response){ return response.data}));
return notifications;
}
So now in my controller when i do
console.log(notifications);
i get this
So how do i use that data? the array of data i want is there... but i can't get it. I thought i could use
notifications.value but that doesn't work
I think the error is that your are sending two return statements in your factory.Change your code to
getAll: function()
{
var temp = $http.get(link).then(function(response){
console.log(response.data);
var notifications = response.data;
return notifications;
});
}
notifications = ($http.get(link)
.success(function(data, status, headers, config){
console.log(data);
return data;
})
.error(function(err) {
return err;
})
);
return notifications;
need to pass more than a single parameter. Originally i was only passing response vice data,status, headers, config

AngularJS: Refreshing service result

I have a service getting items by $http. In the controller I share this data with the view. It works, but when I delete or add new items by $http, I cannot get my list to stay up to date.
I created a refresh() function, that I call every time I add or delete an item, but the refresh applies only from time to time. And not on every action though the function is always duly called and executed.
How should I proceed to get my items refreshed on every action?
Function:
refresh = function() {
itemsService.getItems().then(function(d) {
$scope.items= d;
});
}
Service:
app.factory('itemsService', function($http) {
var itemsService = {
getItems: function() {
return $http.get('items.json')
.then(
function (response) {
return response.data;
}
);
}
};
return itemsService;
});
I have also read about $watch() and tried to make it work in this case, but it does not seem to make any difference:
$scope.$watch('itemsService.getItems()', function(d) {
$scope.items = d;
}, true);
This might be what you are looking for
Angular JS - listen or bind $http request
You can just call your function when the request ends.
You can use an interceptor to do this
var httpinterceptor = function ($q, $location) {
return {
request: function (config) {
//show your loading message
console.log(config);
return config;
},
response: function (result) {
//hide your loading message
console.log('Repos:', result);
return result;
},
responseError: function (rejection) {
//hide your loading message
console.log('Failed with', rejection);
return $q.reject(rejection);
}
}
};
app.config(function ($httpProvider) {
$httpProvider.interceptors.push(httpinterceptor);
});

Use $http once from Angular Service

I need to grab some data from my db through an API and make it accessible throughout my Angular app. I understand that Services are good for storing data to be accessed from multiple controllers. However, in the following code I end up with a new $hhtp.get() each time just to get the same data.
Service:
.factory('Playlist', ['$http', function($http) {
var playlist = {};
playlist.getPlaylist = function() {
return $http.get('api/playlist.php')
.then(function (response) {
var data = response.data;
return data;
})
}
return playlist;
}])
Controllers:
.controller('ScheduleCtrl', ['$http', 'Playlist', function($http, Playlist) {
var self = this;
Playlist.getPlaylist()
.success(function(playlist) {
self.playlist_id = playlist.id;
fetchItems();
})
var fetchScheduleItems = function() {
return $http.get('api/schedule.php/'+self.playlist_id).then(
function(response) {
if (response.data === "null") {
console.log("No items");
} else {
self.items = response.data;
}
}, function(errResponse) {
console.error('Error while fetching schedule');
});
};
}])
.controller('PlaylistItemCtrl', ['$http', 'Playlist', function($http, Playlist) {
var self = this;
Playlist.getPlaylist()
.success(function(playlist) {
self.playlist_id = playlist.id;
fetchItems();
})
var fetchPlaylistItems = function() {
return $http.get('api/schedule.php/'+self.playlist_id).then(
function(response) {
if (response.data === "null") {
console.log("No items");
} else {
self.items = response.data;
}
}, function(errResponse) {
console.error('Error while fetching schedule');
});
};
}])
Is there a way to store the Playlist ID without pinging 'api/playlist.php' from every controller?
Update
Here's a Plunkr based on Abhi's answer: http://plnkr.co/edit/or9kc4MDC2x3GzG2dNeK?p=preview
As you can see in the console, it's still hitting the server several times. I've tried nesting CachedData.save() differently, but it doesn't seem to apply.
I would say store your data locally (CachedData factory - rename it to something that makes sense) and inside your getPlaylist method, before doing http call, check CachedData to see if your data is present and if not, then do the http call.
The code will be something like the below. I have just written it free-hand, so there may be some errors, but you get the picture.
.factory('Playlist', ['$http', 'CachedData', function($http, CachedData) {
var playlist = {};
playlist.getPlaylist = function() {
if (CachedData.data) {
// return cached data as a resolved promise
} else
return $http.get('api/playlist.php')
.then(function (response) {
var data = response.data;
cachedData.save(data);
return data;
})
}
return playlist;
}])
// CachedData factory
.factory('CachedData', function() {
var _data;
var cachedData = {
data: _data,
save: function(newData) {
_data = newData;
}
};
return cachedData;
})
EDIT: Also Remove fetchPlaylistItems from the controller and put it in a factory. The controller is just a glue between your viewmodel and view. Put all your business logic, http calls in a service.
EDIT: I have setup a plunk for you here. I hope it helps.
EDIT: John, the reason you are seeing two server calls is because they are from different controllers ManiCtrl1 and MainCtrl2. By the time, the getPlaylist method from MainCtrl2 is called, the first http request didn't get the chance to finish and save the data. If you add a timeout to MainCtrl2 before calling your service method, you will see that the data is retrieved from cache. See this updated plunk for a demo.
This will be more useful in an app with multiple views, where you don't want to reload data when navigating back to a view. (Ideally, depending on the type of data you are caching, you will have some expiry time after which you would want to reload your data).
You could do some pre validation when calling that method.
var playlist = {};
playlist.playlist = [];
playlist.getPlaylist = function () {
if (playlist.playlist.length <= 0) { //or some lodash _.isEmpty()
$http.get('api/playlist.php')
.then(function (response) {
playlist.playlist = response.data;
})
}
return playlist.playlist;
};
Hope it helps!

Have multiple calls wait on the same promise in Angular

I have multiple controllers on a page that use the same service, for the sake of example we will call the service USER.
The first time the USER.getUser() is called it does an $http request to GET data on the user. After the call is completed it stores the data in USER.data. If another call is made to USER.getUser() it checks if there is data in USER.data and if there is data it returns that instead of making the call.
My problem is that the calls to USER.getUser() happen so quickly that USER.data does not have any data so it fires the $http call again.
Here is what I have for the user factory right now:
.factory("user", function($http, $q){
return {
getUser: function(){
var that = this;
var deferred = $q.defer();
if(that.data){
deferred.resolve(that.data);
} else {
$http.get("/my/url")
.success(function(res){
that.data = res;
deferred.resolve(that.data);
});
}
return deferred.promise;
}
}
});
I hope my question makes sense. Any help would be much appreciated.
Does this work for you?
.factory("user", function($http, $q) {
var userPromise;
return {
getUser: function () {
if (userPromise) {
return userPromise;
}
userPromise = $http
.get("/my/url")
.then(function(res) {
return res.data;
});
return userPromise;
}
}
})
$http already returns the promise for you, even more, in 2 useful types: success & error. So basically, the option that #kfis offered does NOT catch errors and not flexible.
You could write something simple:
.factory('user', function($http) {
return {
getUser: function() {
$http.get('/my/url/')
.success(function(data) {
return data;
})
.error(function(err) {
// error handler
})
}
}
})

Factory does not execute $http.get

My factory does not seem to execute my $http.get. Here's my controller:
app.factory("myService", function($http) {
var myService = {
retrieve: function(id, type) {
var retrievedData = {
device: {},
childDevices: [],
error: {}
};
.
.
.
$http.get(url, headers)
.success(function(data, status) {
// some data post-processing
// some logs
})
.error(function(data, status) {
// some data post-processing
// some logs
});
return retrievedData;
};
return myService;
});
The logs within the $http.get do not print.
I read somewhere I need to use promise, but most examples I saw return $http.get directly. I don't want to return $http.get right away as I need to make some modification on the data in the factory rather than in the controller.
Thanks.
in angular js promise is used for returning response which come from backend. in your code retrievedData return before response come from backend. that's why angular use promise. so when response come from backend it execute success block and success block resolve the promise using deferred.resolve(data) . when error occure then error block get execute and it rejected the promise deferred.reject(err) .but when it resolve the promise it return the response data.
Service Code:
app.factory("myService", function ($http,$q) {
var myService = {
retrieve: function (id, type) {
var deferred = $q.defer();
var retrievedData = {
device: {},
childDevices: [],
error: {}
};
$http.get(url, headers).then(function (data) {
// after success this block execute
deferred.resolve(data);
},
function (err) {
//after error this block execute
deferred.reject(err);
});
return deferred.promise;
}
};
return myService;
});
controller code :
//calling retrive function
myService.retrive(id,type).then(fucntion(data){
...
})
.catch(function(){
...
})
Because when you return your retrievedData it hasn't been retrieved yet. That's why you should use promises:
app.factory("myService", function ($http,$q) {
var myService = {
retrieve: function (id, type) {
var deferred = $q.defer();
var retrievedData = {
device: {},
childDevices: [],
error: {}
};
$http.get(url, headers).then(function (data) {
// success do your success things here and return data
deferred.resolve(data);
},
function (err) {
deferred.reject(err);
});
return deferred.promise;
}
};
return myService;
});
// usage
myService.retrive(id,type).then(function(data){
// data retrived
})

Resources