Data not received by Controller from Service - javascript

My Service looks like
app.service('SupportService', function ($http, $q, $timeout) {
var data = {result:[]};
var getData = function() {
$http.get('/rest/report/logs')
.then(function (response) {
data.result = response.data.result;
console.log("received logs:" + JSON.stringify(response.data.result));
});
};
getData();
return {
data: data.result
};
});
and in my controller, I do
var init = function () {
$scope.logs = SupportService.data;
console.log("logs = " + $scope.logs);
};
init();
When I run this, All I see on console is
logs =
received logs:[{"lastUpdated":"1430433095000","fileName":"java_pid1748.hprof","size":"2826611251","location":"/logs/java_pid1748.hprof"},{"lastUpdated":"1430862157000","fileName":"processor-debug.log","size":"910693","location":"/logs/processor-debug.log"},{"lastUpdated":"1430861106000","fileName":"processor-debug.log.1","size":"10242519","location":"processor-debug.log.1"},{"lastUpdated":"1430862156000","fileName":"processor-error.log","size":"1015578","location":"/logs/processor-error.log"},{"lastUpdated":"1430861106000","fileName":"logs","size":"204","location":"/logs"},{"lastUpdated":"1430862154000","fileName":"error.log","size":"2420","location":"/error.log"},{"lastUpdated":"1430862149000","fileName":"output.log","size":"71","location":"/output.log"}]
As you could see logs are empty, how to I have it wait while data comes from SupportService?
Thanks

When you say $scope.logs = SupportService.data; that is happening instantly - before your $http call is completed. You need to wait for the $http call to complete then extract the data. Generally the best way to do this is to return the promise that the $http creates:
app.service('SupportService', function ($http, $q, $timeout) {
return {
getData: function() {
return $http.get('/rest/report/logs');
};
};
});
And wait for the promise to resolve in your controller:
var init = function () {
SupportService.getData().then(function(response){
$scope.logs = response;
console.log("logs = " + $scope.logs);
}
};
init();

Related

AngularJS service does not return value from http.get

can someone help me with this code? I have problem with return value, function in controller return only
var products = {"id": 3};
I want to collect value from http.get, can someone tell me how to do that??
Controller:
$scope.product = {};
$scope.init = function () {
$scope.loadProducts()
}
$scope.loadProducts = function () {
// $http.get("/products/list").then(function (resp) {
// $scope.products = resp.data;
// })
$scope.products = getListProducts.loadProducts();
}
Service
var myServices = angular.module('myServices', []);
myServices.service('getListProducts', ['$http', function ($http) {
var products = {"id": 3};
this.loadProducts = function () {
$http.get("/products/list").then(function (resp) {
products = resp.data;
})
return products;
}
}]);
you are returning products before http success , instead use promises and resolve when http success
$scope.product = {};
$scope.init = function () {
$scope.loadProducts()
}
$scope.loadProducts = function () {
// $http.get("/products/list").then(function (resp) {
// $scope.products = resp.data;
// })
$scope.productPromise = getListProducts.loadProducts();
productPromise..then(function (resp) {
$scope.products = resp.data;
});
}
Service
var myServices = angular.module('myServices', []);
myServices.service('getListProducts', ['$http', function ($http) {
var products = {"id": 3};
this.loadProducts = function () {
return $http.get("/products/list");
}
}]);
Make use of promises to enforce serialization of your async code.
Refactor your service method as:
this.loadProducts = function () {
var getProducts = new Promise(function(resolve,reject){
$http.get("/products/list").then(function (resp) {
resolve(resp.data);
})
});
return getProducts;
};
And your Controller method as:
getListProducts.loadProducts().then(function(data){
//success callback
$scope.products = data;
});
You can provide the error callbacks as well.
Hope this helps !
You should use promises to return values from your service.
You can use $q in your service. It would help functions to run asynchronously.
myServices.service('getListProducts', ['$http','$q', function ($http,$q) {
var products = {"id": 3};
this.loadProducts = function () {
var deferred = $q.defer();
$http.get("/products/list").then(function (resp) {
products = resp.data;
deferred.resolve(products);
},function(error){
deferred.reject(error);
});
return deferred.promise;
}
}]);
And Your method in controller should handle success and error callbacks :
$scope.loadProducts = function () {
getListProducts.loadProducts().then(function(response){
$scope.products=response;
},function(error){
//your processing logic
});
}
I hope this would help you.

Calling service returning undefined

I am creating a service called ActiveUserProfileService, but when I call its function in a controller I get undefined as a result and I cannot figure out why. The strangest part is that, in the ActiveUserProfileService service, the information from the UserService is displayed through console.log, so I'm receiving the information, but after calling the ActiveUserProfileService in the controller, it gives me undifened. It seems like the data isn't passed around. Can someone help me ?
UserService.js:
(function () {
'use strict';
angular
.module('myApp')
.factory('UserService', UserService);
UserService.$inject = ['$http'];
/* #ngInject */
function UserService($http) {
var service = {
getAuthenticatedUser: getAuthenticatedUser,
getUserInformation: getUserInformation
};
return service;
function getUserInformation(idUser) {
return $http.post('api/user/details', {idUser: idUser});
}
function getAuthenticatedUser() {
return $http.get('api/user');
}
}
})();
ActiveUserProfileService.js
(function () {
'use strict';
angular
.module('myApp')
.factory('ActiveUserProfileService', ActiveUserProfileService);
ActiveUserProfileService.$inject = ['$http','UserService'];
/* #ngInject */
function ActiveUserProfileService($http, UserService) {
var service = {
isAccount: isAccount
};
return service;
////////////////
function isAccount(accountName) {
UserService.getAuthenticatedUser()
.then(function (response) {
var data = response.data;
UserService.getUserInformation(data.user.id)
.then(function (response) {
var userDetails = response.data;
console.log("It is");
console.log(accountName == userDetails.account_types[0].description_internal);
return accountName == userDetails.account_types[0].description_internal;
});
})
}
}
})();
My controller:
(function () {
'use strict';
angular
.module('myApp')
.controller('WizardController', WizardController);
WizardController.$inject = [
'UserService',
'ActiveUserProfileService'
];
/* #ngInject */
function WizardController(UserService,ActiveUserProfileService) {
var vm = this;
console.log("ActiveUserProfileService");
console.log(ActiveUserProfileService.isAccount("professional")); //is Returning me undefined
}
})
();
The point is, you're trying to return a value for isAccount inside another function, a callback. When you do that, you're returning a value to this function, and not isAccount itself, so isAccount will not return anything, undefined, then.
As you are calling an assynchronous method, then isAccount must be assynchronous as well,
Replace
function isAccount(accountName) {
UserService.getAuthenticatedUser()
.then(function (response) {
var data = response.data;
UserService.getUserInformation(data.user.id)
.then(function (response) {
var userDetails = response.data;
console.log("It is");
console.log(accountName == userDetails.account_types[0].description_internal);
return accountName == userDetails.account_types[0].description_internal;
});
})
}
with
function isAccount(accountName) {
var deferred = $q.defer();
UserService.getAuthenticatedUser()
.then(function (response) {
var data = response.data;
//when the user is loaded, then you resolve the promise you has already returned
UserService.getUserInformation(data.user.id)
.then(function (response) {
var userDetails = response.data;
console.log("It is");
console.log(accountName == userDetails.account_types[0].description_internal);
deferred.resolve(accountName == userDetails.account_types[0].description_internal);
return; //here is not isAccount return, but anonymous inner function 'function (response)', you got it?
});
});
return deferred.promise; //return as soon as creates the promise
}
For sure you'd have to inject $q service as well

Angular JS http interceptor async call infinite loop

Hello I try to make a async call in the response method of a http interceptor in AngularJS. The async call gets fired but then gets stuck in an infinite loop and the async call gets called over and over... Not sure why, I guess the error has to do with the structure of my async call
var app = angular.module('AceAngularApi', []);
app.service('Ace',['$http','$q','$injector', '$window', function($http, $q, $injector, $window){
this.user = null;
var setToken = function(token){
$window.localStorage.token = token;
};
var removeToken = function(){
$window.localStorage.token = '';
}
var setCurrentUser = function(currentUser){
user = currentUser;
};
var getCurrentUser = function(){
var self = this;
var url = "http://localhost:8080/api/currentuser";
var response = $http.post(url, {}).then(function(response){
if(response.data.data["obj"]){
self.user = response.data.data["obj"];
}
return response;
});
return response;
};
var currentUser = function(){
return user;
};
return {
setToken: setToken,
setCurrentUser: setCurrentUser,
getCurrentUser: getCurrentUser,
currentUser: this.user,
removeToken: removeToken
}
}]);
app.factory('authInterceptor',['$rootScope', '$q', '$window', '$injector',
function ($rootScope, $q, $window, $injector) {
return {
request: function (config) {
config.headers = config.headers || {};
if ($window.localStorage.token) {
config.headers.Authorization = 'Bearer ' + $window.localStorage.token;
}
return config;
},
response: function(response) {
var deferred = $q.defer();
var Ace = $injector.get('Ace');
Ace.getCurrentUser().then(function(){
deferred.resolve(response);
});
return deferred.promise;
}
};
}]);
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
});
You'll want to add a check in your Ace service so that getCurrentUser is only making one async call, regardless of how many times it is called.
var callStatus = false;
var getCurrentUser = function() {
var self = this;
var url = "http://localhost:8080/api/currentuser";
if(!callStatus) {
callStatus = $http.post(url, {}).then(function(response){
if(response.data.data["obj"]){
self.user = response.data.data["obj"];
}});
}
return callStatus;
};

AngularJS : How to test a promise resolved in a callback function

I have written a function which opens an indexedDB. I'm using a promise, because I think it is the cleanest way to handle this.
this.$get = function($q, $rootScope, $window) {
return {
finalize: function() {
var deferred = $q.defer();
var dbRequest = $window.indexedDB.open(dbName, dbVersion);
dbRequest.onupgradeneeded = function(event) {
// XXX do something here.
};
dbRequest.onsuccess = function(event) {
db = event.target.result;
console.log('Success!');
deferred.resolve(event);
};
dbRequest.onerror = deferred.reject;
return deferred.promise;
}
};
};
In order to test this, I have created the following test function:
describe('finalize', function() {
it('should initialize the database', function(done) {
var promise = resource.finalize();
promise.then(function() {
console.log('resolved');
var transaction = resource.db.transaction(['Component']);
expect(transaction).toBeDefined();
done();
});
$rootScope.$apply();
});
});
This prints 'Success!' in the console, but the promise is never resolved.
If I move $rootScope.$apply() to the end of the onsuccess function, the promise is resolved, but only for one test. Other tests then throw an error Error: [$rootScope:inprog] $digest already in progress.
How should I resolve this promise? Is a callback function better?
this.$get = function($q, $rootScope, $window) {
return {
finalize: function() {
var deferred = $q.defer();
var dbRequest = $window.indexedDB.open(dbName, dbVersion);
dbRequest.onupgradeneeded = function(event) {
// XXX do something here.
};
dbRequest.onsuccess = function(event) {
db = event.target.result;
console.log('Success!');
$rootScope.$apply(function () {
deferred.resolve(event);
});
};
dbRequest.onerror = function (error) {
$rootScope.$apply(function () {
deferred.reject(error);
});
}
return deferred.promise;
}
};
};
Also you should use var promise = resource.finalize(); one time for all tests

Using a factory and controller to return data

I have the following factory:
app.factory('clientFactory', function ($http) {
var factory = {};
factory.getClients = function () {
var url = "/tracker/api/client";
$http.get(url).then(function (response) {
return response.data;
});
};
factory.getClient = function (id) {
// TODO
};
factory.insertClient = function (firstName, lastName, city) {
// TODO
};
factory.deleteClient = function (id) {
// TODO
};
return factory;
});
And the controller:
app.controller('ClientController', function ($scope, clientFactory) {
$scope.clients = [];
init();
function init() {
$scope.clients = clientFactory.getClients();
}
$scope.insertCustomer = function () {
// TODO
};
$scope.deleteCustomer = function (id) {
// TODO
};
});
In my controller, 'clients' is always null. I've tried a couple of other approaches like what I see here but I got an error that 'success cannot be called on null' and if I make it past that error, my success function is never called.
What am I missing here?
In your controller, you are treating the getClients method as if it were synchronous. Remember that when you do $http.get, a promise is returned. You need to return that promise to the controller, so it can call .then with a method which will handle a successful result.
Your getClients method needs to look like this:
factory.getClients = function () {
var url = "/tracker/api/client";
return $http.get(url);
};
And I believe your init method needs to look like this:
function init() {
clientFactory.getClients().then(function(response) {
$scope.clients = response.data;
});
}
Try that out!

Categories

Resources