I'm a bit new to angular and am trying to understand how I can use a promise with two services.
In the code below in the App.js I call FirstService.get(), which should wait for the RestService to return the result. In the App.js I would like to use the .then() to wait for the result from FirstService.get().
My question how do I need to set up the promise in the First Service so that I can use the .then() in the App.js?
Thanks!
// App.js
FirstService.get().then(function(promise) {
// do something here with the result
}, function(response) {
console.log('error');
});
//First Service
oApp.service( 'FirstService', function( RestService, $localStorage, $q ) {
this.get = function( ) {
var url = o.buildServerUrl();
// Retrieve info
RestService.get(url, function(response) {
return response;
});
};
});
// Rest Service
oApp.service( 'RestService', function( $rootScope, $http ) {
this.get = function ( url, callback ) {
try {
$http.get(url).
success(function(data, status, headers, config) {
var response = o.processServerResponse(data, status);
callback(response);
}).
error(function(data, status, headers, config) {
var response = o.processServerResponse(data, status);
callback(response);
});
}
catch(err) {
var response = o.createExceptionResponse(err.message);
callback(response);
}
}
});
This should do it:
// App.js
FirstService.get().then(function(promise) {
// do something here with the result
}, function(response) {
console.log('error');
});
//First Service
oApp.service( 'FirstService', function( RestService, $localStorage, $q ) {
this.get = function( ) {
var deferred = $q.defer();
var url = o.buildServerUrl();
// Retrieve info
RestService.get(url, function(response) {
deferred.resolve(response);
});
return deferred.promise;
};
});
// Rest Service
oApp.service( 'RestService', function( $rootScope, $http ) {
this.get = function ( url, callback ) {
try {
$http.get(url).
success(function(data, status, headers, config) {
var response = o.processServerResponse(data, status);
callback(response);
}).
error(function(data, status, headers, config) {
var response = o.processServerResponse(data, status);
callback(response);
});
}
catch(err) {
var response = o.createExceptionResponse(err.message);
callback(response);
}
}
});
Related
I make a few different $http calls and I want to set either variable (var blah) or $scope to be set to an object value and persist at least down a few lines so that it can be sent to a 2nd $http request
I get undefined , why and how to fix / persist the variable or scope?
app.controller('detailController', function ($scope, $interval, $http, $routeParams, $window, sessionVariables, $httpParamSerializer) {
//$scope.xid = 1; // this seems to persist but NOT if i try update it in 1st $http.get
$http.get('/Umbraco/Api/ClientsApi/GetClient/' + clientId).
success(function (data, status, headers, config) {
console.log(data); // correctly shows me object of data
$scope.xid = data.Id; // DOES NOT WORK OUTSIDE OF this $http.get
console.log(data.Id); // yes shows data inside here
//console.log(data.IsSampleData); // contains data
$scope.client = data; // this is how is then use client object in view template
}).
error(function (data, status, headers, config) {
// log error
});
This is the problem, $scope.xid does is saying undefined
console.log('before');
console.log($scope.xid);
console.log('after');
Of which this 2nd $http.get call I want to append the xid onto the end of it
$http.get('/Umbraco/Api/ActivityApi/GetActivity').
success(function (data, status, headers, config) {
$scope.activity = data; // correctly gets data
}).
error(function (data, status, headers, config) {
// log error
});
Update : FULL CODE
app.controller('detailController', function ($scope, $interval, $http, $routeParams, $window, sessionVariables, $httpParamSerializer) {
var clientId = $routeParams.id;
//console.log(clientId);
//$scope.xid = 1;
$http.get('/Umbraco/Api/ClientsApi/GetClient/' + clientId).
success(function (data, status, headers, config) {
console.log(data);
//console.log(data.Id);
//console.log(data.IsSampleData);
$scope.client = data;
}).
error(function (data, status, headers, config) {
// log error
});
console.log('before');
console.log(client.Id);
console.log('after');
$http.get('/Umbraco/Api/ActivityApi/GetActivity').
success(function (data, status, headers, config) {
//console.log(data);
//console.log(data.IsSampleData);
$scope.activity = data;
}).
error(function (data, status, headers, config) {
// log error
});
});
Use Promises and chaining
var firstRequest = $http.get(url).then(function (result) {
/* optional - do something with result, pass through to next .then() */
return result;
});
var secondRequest = firstRequest.then(function (result) {
return $http.get(otherUrl);
});
var thirdREquest = secondRequest.then(function () {
/* and so on */
});
You are setting $scope.xid once the promise returnet by $http.get() is resolved.
Actually the console.log($scope.xid) executes before than the assignment!
If you want to use the result of a first promise, you can chain promises like this:
$http.get('/Umbraco/Api/ClientsApi/GetClient/' + clientId)
.then(function(response) {
return $http.get('/Umbraco/Api/ActivityApi/GetActivity' + response.Id)
)
.then(function(response2) {
// Proccess response2
});
try this:
app.controller('detailController', function ($scope, $interval, $http, $routeParams, $window, sessionVariables, $httpParamSerializer) {
var clientId = $routeParams.id;
//console.log(clientId);
//$scope.xid = 1;
$http.get('/Umbraco/Api/ClientsApi/GetClient/' + clientId).then(function (response) {
console.log(response.data);
//console.log(response.data.Id);
//console.log(response.data.IsSampleData);
$scope.client = response.data;
// second HTTP call with chained client ID received from the first call
$http.get('/Umbraco/Api/ActivityApi/GetActivity/' + response.data.Id).then(function (response2) {
//console.log(response2.data);
//console.log(response2.data.IsSampleData);
$scope.activity = response2.data;
}).catch(function (error) {
// log error
});
}).catch(function (error) {
// log error
});
// this code is outside of $http promise as it is executed before promise resolve
// so, at this point $scope.client.Id is undefined
//console.log('before');
//console.log($scope.client.Id);
//console.log('after');
});
This code does seem to "work" Any reason why I should NOT do this?
$http.get('/Umbraco/Api/ClientsApi/GetClient/' + clientId).
success(function (data, status, headers, config) {
$scope.client = data;
$scope.getActivity(data); // CALL HERE
}).
error(function (data, status, headers, config) {
// log error
});
$scope.getActivity = function(data) {
$http.get('/Umbraco/Api/ActivityApi/GetActivity').
success(function(data, status, headers, config) {
$scope.activity = data;
}).
error(function(data, status, headers, config) {
// log error
});
};
use then() for $http according to official documentation
$http.get('/Umbraco/Api/ActivityApi/GetActivity').then(
function success(response) {
console.log(response.data);
console.log(response.data.Id);
$scope.client = response.data;
},
function error(response) {
console.log(response);
}
);
EDIT !
Http is asynchronous, it take some time to do it.
It mean that $http is called, and the answer IS NOT WAITED. the code after it is runned immediatly !
console.log("before $http");
$http.get('/Umbraco/Api/ActivityApi/GetActivity').then(
function success(response) {
console.log("http success");
$scope.client = response.data;
},
function error(response) {
console.log("http error");
console.log(response);
}
);
// this will be logged before the success/error of http
console.log("after $http");
If you want to do something when success is done, create a function for it and call it from success/error
My factory returns undefined when I invoke the method getPopularMovies in factory using controller, Am not sure what mistake I have done here, Please let me know
my factory
angular.module('ngMovies').factory('moviesFactory', function ($http) {
var movies = [];
function getPopularMovies() {
var popularmoviesurl = "https://api.themoviedb.org/3/movie/popular?api_key=adf3d78d5c0f38313a68de730f02063a";
return $http({method: 'GET', url: popularmoviesurl}).success(function (data, status, headers, config) {
if (status == 200) {
movies = data.results;
} else {
console.error('Error happened while getting the movie list.')
}
}).error(function (data, status, headers, config) {
console.error('Error happened while getting the movie list.')
});
return movies;
}
return {
getPopularMovies: getPopularMovies
}
});
controller
angular.module('ngMovies').controller('popularmoviesController', ['moviesFactory', '$scope', function (moviesFactory, $scope) {
$scope.popularmovies = moviesFactory.getPopularMovies();
}]);
I suggest to use promises for asynchronous processes.
function getPopularMovies()
{
var deferred = $q.defer();
var popularmoviesurl = "https://api.themoviedb.org/3/movie/popular?api_key=adf3d78d5c0f38313a68de730f02063a";
$http({method:'GET',url:popularmoviesurl}).
success(function (data, status, headers, config) {
if (status == 200) {
deferred.resolve(data.results);
} else {
console.error('Error happened while getting the movie list.')
deferred.reject();
}
}).error(function (data, status, headers, config) {
deferred.reject();
console.error('Error happened while getting the movie list.')
});
return deferred.promise;
}
and then inside your controller just use
moviesFactory.getPopularMovies().then(function(data){
$scope.popularmovies = data;
},function(){
// your error handling
})
service:
angular
.module('ngMovies')
.factory('moviesFactory', function($http) {
function getPopularMovies(callback) {
var popularmoviesurl = "https://api.themoviedb.org/3/movie/popular?api_key=adf3d78d5c0f38313a68de730f02063a";
return $http({
method: 'GET',
url: popularmoviesurl
}).
success(function(data, status, headers, config) {
if (status == 200) {
callback(data.results);
} else {
console.error('Error happened while getting the movie list.')
}
}).
}
return {
getPopularMovies: getPopularMovies
}
});
controller:
angular
.module('ngMovies')
.controller('popularmoviesController', ['moviesFactory', '$scope', function(moviesFactory, $scope) {
moviesFactory.getPopularMovies(function(movies){
$scope.popularmovies = movies;
});
}]);
Change your controller code like this:
angular.module('ngMovies').controller('popularmoviesController', ['moviesFactory', '$scope', function (moviesFactory, $scope) {
moviesFactory.getPopularMovies().then(function(data) {
$scope.popularmovies = data.results;
});
}]);
And in the getPopularMovies method return movies; statement is not required since you have already returned above in the same method.
I'm creating service layers to interact with Rest server, but I've got some problems with ngResource promises.
var grupogestion= angular.module('app.grupogestion.services', ['ngResource']);
grupogestion.factory('Grupogestion', ['$resource', function ($resource){
return $resource('api/grupogestiones/:action/:id.:format',
{
action: '#action', id:'#id', format:'json'
},
{
'get': {method:'GET'},
'post': {method:'POST',headers : {'Content-Type': 'application/x-www-form-urlencoded'}},
'save': {method: 'POST',headers : {'Content-Type': 'application/x-www-form-urlencoded'}}
}
);
}]);
grupogestion.service('GrupogestionService',['Grupogestion', function (Grupogestion){
this.findAll = function (){
Grupogestion.get({action: 'index'},function (data, status, headers, config){
return data;
});
}
this.save = function (grupogestion){
Grupogestion.save({'action':'add'},$.param(grupogestion)).$promise.then(
function(data){
alert('k');
return data;
},
function(error){
alert('j');
return error;
}
);
}
}]);
When I call var response = GrupogestionService.save(data) from angular controller, I don't get the data at the same time I call the function, so the question is: How can I modify GrupogestionService for returning data to the controller?
I've tried to return the promise but I couldn't do it. Thanks for helping.
// service code
grupogestion.service('GrupogestionService', ['Grupogestion', function (Grupogestion) {
this.findAll = function () {
Grupogestion.get({action: 'index'}, function (data, status, headers, config) {
return data;
});
};
this.save = function (grupogestion) {
return Grupogestion.save({'action': 'add'}, $.param(grupogestion));
}
}]);
//run in your controller
var response = GrupogestionService.save(data).$promise.then(
function (data) {
alert('k');
return data;
},
function (error) {
alert('j');
return error;
}
);
My app has a service that is supposed to return an array of objects (tweets from the twitter api) that looks like:
.service('twitterService', function($http) {
this.getTweets = function(){
$http.get('http://example.com/?json=get_twitter_sidebar').success(
function(data, status, headers, config) {
if (data.status == 'ok') {
return data.feed;
} else {
return 'Error Retrieving Feed'
}
});
}
})
This service seems to work; it calls the api and returns the desired object array (I used console.log to verify). However, I can't seem to pass the returned array to my controller:
var TopPageCtrl = function($scope, $window, $http, twitterService) {
$scope.feed = twitterService.getTweets();
};
When I use console.log($scope.feed), it returns undefined. I've tried a million approaches but nothing seems to work. What am I doing wrong?
return the promise
.service('twitterService', function($http) {
this.getTweets = function(){
var p = $http.get('http://example.com/?json=get_twitter_sidebar').success(
function(data, status, headers, config) {
if (data.status == 'ok') {
return data.feed;
} else {
return 'Error Retrieving Feed';
}
});
return p;
}});
var TopPageCtrl = function($scope, $window, $http, twitterService) {
twitterService.getTweets().then(function (response) {
$scope.feed = response;
};};
Maybe it's returning a promise that needs to be resolved? Try something like...
var getFeed = twitterService.getTweets();
getFeed.then(function (feed) {
$scope.feed = feed;
});
$scope.feed = twitterService.getTweets();
this.getTweets = function(){
$http.get('http://example.com/?json=get_twitter_sidebar').success(
function(data, status, headers, config) {
if (data.status == 'ok') {
return data.feed;
} else {
return 'Error Retrieving Feed'
}
});
}
Your function isn´t returning anything, that´s why you are getting "undefined"..
Try this:
this.getTweets = function(){
return $http.get('http://example.com/?json=get_twitter_sidebar').success(
function(data, status, headers, config) {
if (data.status == 'ok') {
return data.feed;
} else {
return 'Error Retrieving Feed'
}
});
}
twitterService.getTweets().then(function (response){...});
Following is my Service code -
myApp.service('loginServiceChk', function(){
this.getInfo = {};
this.chkLogin = function($http,$location,$window){
$http.get('/users/chklogin')
.success(function (data, status, headers, config) {
if (data.code!="200"){
this.getInfo = {};
$window.location.href='/#/users/login';
}else{
this.getInfo = data.usersession;
}
});
};
});
My controller code -
myApp.controller('userDash',function($scope,$http,$location,loginServiceChk,$window){
loginServiceChk.chkLogin($http,$location,$window);
console.log(loginService.getInfo);
$scope.userLogout = function() {
$http.get('/users/logout').success(function (data, status, headers, config) {
if (data.logout=="200"){
merInfo = {} ;
$window.location.href='/#/userss/login';
}
})
};
});
However I am always getting an empty object in the console ( console.log(loginService.getInfo); ) . Let me know what I am doing wrong here.
I am expecting session data in the this.getInfo.
EDIT
If I am using .then then it is going in the if ie if (data.code!="200"){ here.
You have to wait for the promise.
Use this in your controller:
loginServiceChk.chkLogin($http,$location,$window).then(function() {
console.log(loginService.getInfo);
});
And add return to your service:
this.chkLogin = function($http,$location,$window){
return $http.get('/users/chklogin')
.then(function (data, status, headers, config) {
if (data.code!="200"){
this.getInfo = {};
$window.location.href='/#/users/login';
}else{
this.getInfo = data.usersession;
}
});
};