Angular JS http interceptor async call infinite loop - javascript

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;
};

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.

not able to pass data to a data object in angularjs

N.B: I'm pretty much new to angularJS programming. What I'm trying to do is, to save info returned by a service to an object. My object looks like this.
var userObject = {
"id": "1",
"firstName": "Amelia",
"lastName": "Earheart"
};
I have a factory that returns data from back end and it looks like this:
.factory('myService', function($http) {
var baseUrl = 'backendservice/';
return {
myInfo:function() {
return $http.get(baseUrl + 'getmyInfo');
}
};
})
And this is how my Controller communicates with the factory service:
.controller('myController', function($routeParams,myService) {
var my = this;
my.basicInfo = function () {
//to get my info
myService.myInfo().success(function(data) {
my.activeUser.myData.id = data.id;
my.activeUser.myData.firstName = data.firstName;
my.activeUser.myData.lastName = data.lastName;
});
};
my.addSomething = function(post) {
var userObject = my.basicInfo();
};
});
and this is how I assign the data to userObject
var userObject = my.basicInfo();
I don't know why it's not working. Factory service runs but the value is not assigned to userObject.
My Controller as whole looks like this:
(function() {
angular
.module('myApp.spa', [])
.factory('myService', function($http) {
var baseUrl = 'backendservice/';
return {
myInfo:function() {
return $http.get(baseUrl + 'getmyInfo');
}
};
})
.controller('myController', function($routeParams,myService) {
var my = this;
my.basicInfo = function () {
//to get my info
myService.myInfo().success(function(data) {
my.activeUser.myData.id = data.id;
my.activeUser.myData.firstName = data.firstName;
my.activeUser.myData.lastName = data.lastName;
});
};
my.addSomething = function(post) {
var userObject = my.basicInfo();
};
});
})();
Your function my.basicInfo() does not return anything so the value of your variable userObject is undefined. Also if you want to use userObject on view expose it on your controller instance as my.userObject.
If you want to assign a value to userObject, do it either within the success callback of my.basicInfo() method or return a promise from the method my.basicInfo() and assign the value in then callback of the promise
Approach 1
my.basicInfo = function () {
//to get my info
var activeUser = {};
return myService.myInfo()
.then(function(response) {
angular.extend(activeUser, response.data);
my.userObject = activeUser;
});
};
Approach 2
my.basicInfo = function () {
//to get my info
var activeUser = {};
return myService.myInfo()
.then(function(data) {
angular.extend(activeUser, response.data);
return activeUser;
});
};
my.addSomething = function(post) {
my.basicInfo()
.then(function (response) {
my.userObject = response;
});
};
Reason is my.basicInfo does not return anything and also from $http.success/failure, you can not return any value.
So in this case, following steps you would have to do:
Define var userObject at the top of your controller so that can be accessible to all the methods.
Assign data to userObject inside success callback of $http
(function() {
angular
.module('myApp.spa', [])
.factory('myService', function($http) {
var baseUrl = 'backendservice/';
return {
myInfo:function() {
return $http.get(baseUrl + 'getmyInfo');
}
};
})
.controller('myController', function($routeParams,myService) {
var my = this;
var userObject;
my.basicInfo = function () {
//to get my info
myService.myInfo().success(function(data) {
my.activeUser.myData.id = data.id;
my.activeUser.myData.firstName = data.firstName;
my.activeUser.myData.lastName = data.lastName;
userObject = data;
});
};
my.addSomething = function(post) {
my.basicInfo();
};
});
})();
.factory('UserInfo', function($resource, apiHost) {
return $resource(apiHost + '/userinfo/:userId');
});
.controller('myController', function($routeParams,UserInfo) {
var vm = this;
// suppose that you have stored the userId somewhere after the login
vm.userObject = {};
var myUserInfo = UserInfo.get({
userId: userId
});
vm.refreshData = function (){
myUserInfo.$promise
.then(function(response) {
vm.userObject = response;
}, function(error) {
// doSomething
});
};
vm.update = function(){
myUserInfo.save(vm.userObject, function() {
// console.log('success');
}, function(error) {
// console.log('error');
});
};
});

Struggling to return result to scope from factory

I'm trying to return the filtered object from a factory. At the point of "return getTheChosen" the object is as expected. I can't assign it to my $scope.postDetail!
Any advice appreciated!
app.factory('postsFactory', function ($http) {
var response = $http.get('http://myjsonendpoint.com/');
var factory = {};
factory.list = function () {
return response;
};
factory.get = function (id) {
var getTheChosen = factory.list().then(function (res) {
var chosen = _.find(res.data, {'id': id});
return chosen;
});
return getTheChosen;
};
return factory;
});
then...
app.controller('ThoughtsController', function ($scope, postsFactory) {
postsFactory.list()
.then(function (data) {
$scope.posts = data;
});
});
then...
app.controller('PostDetailController', function ($scope, postsFactory, $routeParams) {
$scope.postDetail = postsFactory.get(parseInt($routeParams.postId));
$scope.test = 'yep';
});
Do it another way in your PostDetailController:
postsFactory.get(parseInt($routeParams.postId)).then(function(data) {
$scope.postDetail = data;
});
Instead of:
$scope.postDetail = postsFactory.get(parseInt($routeParams.postId));
Hope this will work

AngularJS: could not access Object property in the controller

this is my object that get from a service.
this is my controller.
var user = useroneService.getLoggedUser(user);
console.log(user);
console.log(user.data);
I got a undefined when I try to access the data. How do I access to the Object data?
user.service.js
'use strict';
angular.module('app').service('userService',['authService', 'userTransformer','LoggedUser', function(authService, userTransformer, LoggedUser) {
this.getLoggedUser = function(user){
return authService.login(user).then(function (response) {
var loggedUser = userTransformer.transform(response.data);
});
};
}]);
logged.user.js
angular.module('app').value('LoggedUser', function () {
var LoggedUser = function () {
this.dispalyName = '';
this.token = '';
this.logged = false;
};
LoggedUser.prototype = {
};
});
user.transformer.js
angular.module('app').factory('userTransformer',['LoggedUser', function (LoggedUser) {
//logged user transform
var transformObject = function (response) {
var model = new LoggedUser();
angular.extend(model, response);
return model;
};
return {
transform: transformObject
};
}]);
flow
AuthService(get data)==>UserService(data transform to LoggedUser using the transformer)
==>LoginController
You are not returning a promise. Change your controller code to:
useroneService.getLoggedUser(user).then(function(data) {
var user = data;
console.log(user);
})
One more thing, you are not returning the response from your service:
return authService.login(user).then(function (response) {
var loggedUser = userTransformer.transform(response.data);
return loggedUser; //add this
});

Data not received by Controller from Service

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();

Categories

Resources