I'm trying to clean up my controller by doing http requests in services, but for some reason a functions in my controller is not getting a response from a service.
I have this function in my controller,
$scope.addMovie = function() {
addMovie.add().then(function(response){
if(response){
console.log ('Response')
} else {
console.log ('No reposone')
}
});
And this is the service,
(function(){
"use strict";
angular.module('addMovieseat')
.factory('addMovie',
function($http, $q){
return{
add: function(){
var deferred = $q.defer();
'http://api.themoviedb.org/3/movie/206647?api_key=a8f7039633f2065942cd8a28d7cadad4&append_to_response=releases'
// Search for release dates using the ID.
var base = 'http://api.themoviedb.org/3/movie/';
var movieID = $(event.currentTarget).parent().find('.movieID').text()
var apiKey = 'a8f7039633f2065942cd8a28d7cadad4&query='
var append_to_response = '&append_to_response=releases'
var callback = 'JSON_CALLBACK'; // provided by angular.js
var url = base + movieID + '?api_key=' + apiKey + append_to_response + '&callback=' + callback;
$http.jsonp(url,{ cache: true}).
success(function(data, status, headers, config) {
if (status == 200) {
deferred.resolve(data.results);
console.log ('Succes getting data')
} 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.')
deferred.resolve(false);
});
$(".search_results").fadeOut(250);
return deferred.promise;
}
}
})
})();
When I run the $scope.addMovie function from the controller the console log shows a Succes getting data from the service and then a No response from the function in the controller. What's missing here?
//edit. I'm now trying to insert the data from the service into a scope in my controller,
$scope.addMovie = function() {
$scope.movieListID = {};
console.log ('empty' + $scope.movieListID)
movieAdd.add()
.then(function(response){
$scope.movieListID = response;
console.log ('Not empty' + $scope.movieListID)
})
.catch(function(response) {
console.log ('No search reposone')
});
}
but the console log displays a "undefined" message afther the "Response OK".
try to change this
$scope.addMovie = function() {
addMovie.add().then(function(response){
if(response){
console.log ('Response')
} else {
console.log ('No reposone')
}
});
to this:
$scope.addMovie = function() {
addMovie.add()
.then(function(response){
console.log ('Response OK');
})
.catch(function(responce){
console.log ('Response error');
});
like this you are actually catching any errors which may be happening in you factory/service...
Related
I need to finish all my ajax calls to enable a button, but I am not getting all my promises done before enabling the button.
I have this piece of code with all my ajax gets:
$q.all([
$scope.load_ocupacoes(),
$scope.load_tipos_pisos(),
$scope.load_tipos(),
$scope.load_caracteristicas(),
$scope.load_amenidades(),
$scope.load_subtipos(true, 'incluir')
]).then(function() {
console.log('loading complete !!!');
$scope.theglyphicon = 'fa fa-check fa-fw';
$scope.isDisabledButton = false;
});
Each load function is a $http.get, like that:
$scope.load_ocupacoes = function() {
$http.get(url_api_status_ocupacao)
.success(function(response) {
console.log(response);
$scope.status_ocupacoes = response;
})
.error(function(response) {
console.log(response);
ngToast.create({
className: 'danger',
content: 'Não foi possível recuperar a lista.'
});
});
};
I have also tried this way:
$scope.load_ocupacoes = function()
{$resource(url_api_status_ocupacao).query().$promise.then(function(response) {
console.log(response);
$scope.status_ocupacoes = response;
});
};
And this... but with the same problem:
$scope.load_ocupacoes = function() {
$timeout(function(){
$scope.$apply(function() {
$scope.status_ocupacoes = appFactory.recuperarLista(url_api_status_ocupacao)
.then(function(result) {
console.log(result);
$scope.status_ocupacoes = result;
});
});
});
};
But, I am getting the message 'loading complete !!!' before the end of all loading.
Is there any problem with this approach?
There could be more errors, but the basic misunderstanding is that $q.all takes promises, and all your functions return undefined (because they don't have a return statement) - so instead of getting six promises, your $q.all gets six undefineds. AFAIK, $http.get returns a promise by default, so one way to fix it would be to just add return statement to each of your functions, in front of $http.get, like this:
$scope.load_ocupacoes = function() {
return $http.get(url_api_status_ocupacao)
.then(function(response) {
});
};
I guess $q.all accept promises.
This must be apply to all other's related method.
$scope.load_ocupacoes = function() {
$http.get(url_api_status_ocupacao)
// use then instead success
.then(function(response) {
// return raw promise instead actual value
return response;
}, console.log('error));
};
$q.all requires an array of promises but your are providing a function which is neither returning any promise.
You can do this :
$q.all([
$http.get(url_api_status_ocupacao),
$http.get(url_api1),
$http.get(url_api2)
]).then(function() {
......
});
I have resolved my problem with this approach:
var promises = [appFactory.recuperarLista(url_api_status_ocupacao),
appFactory.recuperarLista(url_api_tipos_pisos),
appFactory.recuperarLista(url_api_caracteristicas),
appFactory.recuperarLista(url_api_amenidades)
];
$q.all(promises).then(function (responses) {
$scope.status_ocupacoes = responses[0];
$scope.tipos_pisos = responses[1];
$scope.caracteristicas = responses[2];
$scope.amenidades = responses[3];
}).then(function() {
console.log('All Loading completed !!!');
});
And I made a factory returning promises:
angular.module('starter.services', ['datatables'])
.factory('appFactory', function($http, $q) {
return {
recuperarLista: function(url) {
var deferred = $q.defer();
$http({ method: "GET", url: url })
.success(function (data, status, headers, config) {
deferred.resolve(data);
}).error(function (data, status, headers, config) {
deferred.reject(status);
});
console.log('loading for ' + url + ' was completed !!!');
return deferred.promise;
}
};
});
Now I am getting this console output:
loading for api/loadliststatusocupacoes was completed !!!
services.js:171
loading for api/loadlisttipospisos was completed !!!
services.js:171
loading for api/loadlistcaracteristicas was completed !!!
services.js:171
loading for api/loadlistamenidades was completed !!!
services.js:171
All Loading completed !!!
imovel-controller.js:690
In my app.config i need to retrieve a value from a service but i have an error message : UserServiceProvider.getUser is not a function. The goal is to allow the user to access some pages only if he is a part of a list.
Here's my service code :
var app = angular.module('myApp');
app.service('UserService', '$http', '$q', function(){
userService.getUser = function () {
var deferred = $q.defer();
return $http.get(userUrl + "getUserName")
.success(function (data) {
deferred.resolve(userService.userName = data);
console.log(data);
//alert('Success loading user');
}).error(function (error) {
deferred.reject(error);
//alert('Error loading user' + error.message);
})
return deferred.promise;
}
return userService;
});
My config :
app.config(function(UserServiceProvider){
UserServiceProvider.getUser()
.then(function (data) {
console.log(UserServiceProvider.userName);
});
});
I'm trying to traverse the data I get from a service into a scope in my controller, but I can't get the last step right (I think). I added steps to see if perhaps inserting the data into the scope happens before the actual request from the service, but that's not the case.
Step 1: I activate the addMovie function in the controller.
Step 2: I create an empty movieListID scope.
$scope.addMovie = function() {
console.log ('Step 1: start addMovie function in controller')
console.log ('Step 2: create empty movieListID scope')
$scope.movieListID = {};
console.log ($scope.movieListID)
movieAdd.add()
.then(function(response){
$scope.movieListID = response;
console.log ('Step 4: Succes inserting data into scope' + $scope.movieListID)
})
.catch(function(response) {
console.log ('No search reposone')
});
}
Step 3: Get the data from the service.
(function(){
"use strict";
angular.module('addMovieseat')
.factory('movieAdd',
function($http, $q){
return{
add: function(){
var deferred = $q.defer();
'http://api.themoviedb.org/3/movie/206647?api_key=a8f7039633f2065942cd8a28d7cadad4&append_to_response=releases'
// Search for release dates using the ID.
var base = 'http://api.themoviedb.org/3/movie/';
var movieID = $(event.currentTarget).parent().find('.movieID').text()
var apiKey = 'a8f7039633f2065942cd8a28d7cadad4&query='
var append_to_response = '&append_to_response=releases'
var callback = 'JSON_CALLBACK'; // provided by angular.js
var url = base + movieID + '?api_key=' + apiKey + append_to_response + '&callback=' + callback;
$http.jsonp(url,{ cache: true}).
success(function(data, status, headers, config) {
if (status == 200) {
deferred.resolve(data.results);
console.log ('Step 3: Succes getting data')
} 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.')
deferred.resolve(false);
});
$(".search_results").fadeOut(250);
return deferred.promise;
}
}
})
})();
Step 4:
movieAdd.add()
.then(function(response){
$scope.movieListID = response;
console.log ('Step 4: Succes inserting data into scope' + $scope.movieListID)
But when I get to step 4 I get a "undefined" returned in the console log, which refers to the $scope.movieListID
Also if I check the network tab in Chrome I see that the json request has been done. So the data is inside the service. But getting it into the scope is not working.
As soon as Html page gets loaded, it calls SuperCategoryController, where i am assigning supercategories to $scope variable.
$scope.SuperCategories = SuperCategoryService.GetSuperCategories();
But as this controller is depends on service, which in turn calls the http request. so at the time pf assignment http request is not completed. so $scope.SuperCategories is getting assiged to undefined.
sampleApp.service('SuperCategoryService', ['$http', function ($http){
var URL = 'http://localhost/cgi-bin/superCategory.pl';
var SuperCategories;
$http({
method: 'POST',
url: URL,
data: "action=GET",
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).
success(function (data) {
alert (data);
if (data != null || data != 'undefined') {
SuperCategories = data;
}
})
.error(function (error) {
alert (error.message);
//$scope.status = 'Unable to retrieve super categories' + error.message;
});
//simply returns the SuperCategories list
this.GetSuperCategories = function () {
//alert (SuperCategories);
return SuperCategories;
}
}]);
sampleApp.controller('SuperCategoryController', ['$scope', 'SuperCategoryService', function ($scope, SuperCategoryService){
$scope.SuperCategories = SuperCategoryService.GetSuperCategories();
$scope.LoadSuperCategoryMapping = function()
{
alert ($scope.SelectedSuperCategory.id);
}
}]);
How to solve this problem in proper way.
I haven't tried this code myself but I would approach a solution using factory and a promise to make sure the data has been loaded. Something along these lines:
sampleApp.factory('SuperCategoryService', ['$http', function ($http){
return {
GetSuperCategories: function () {
var URL = 'http://localhost/cgi-bin/superCategory.pl';
return $http.get(URL);
}
}
}]);
sampleApp.controller('SuperCategoryController', ['$scope', 'SuperCategoryService', function ($scope, SuperCategoryService){
$scope.SuperCategories = function() {
SuperCategoryService.GetSuperCategories()
.then(function(d) {
if (d.data != undefined) {
// Your data should be loaded here
console.log(d.data);
$scope.SuperCategories = d.data;
}
})
.error(function(data, status) {
// Errors here
});
}
}]);
On my app, I need to recover data (json) by making multiples validations using http requests before all my app starts. So my problem is that I'm using angular.run() to make all the http requests and resolving all of the validations with promises.
The problem is, not all of my promises are executed before my app is started.
part of my code is:
appModule.run(configRun);
configRun.$inject = [
'$http', '$rootScope', 'gettextCatalog', 'ipLoadDataService',
'webStorageService', 'ipDataSetParserService'];
function configRun($http, $rootScope, gettextCatalog, ipLoadDataSrv, webStrSrv, dataSetParser) {
webStrSrv.clear();
ipLoadDataSrv.getHeadDataSet2()
.then(function (responseHead) {
if (ipLoadDataSrv.updatedDataSet2(responseHead.headers["last-modified"])) {
//save into localstorage
webStrSrv.clear();
webStrSrv.setItem("last-modified", { date: responseHead.headers["last-modified"] });
ipLoadDataSrv.getDataSet2()
.then(function (responseData) {
$rootScope.cabecera = responseData;
})
}
})
}
// LoadDataService
appModule.factory('ipLoadDataService', loadDataService);
loadDataService.$inject = ['$http',
'$q',
'webStorageService',
'myPrjEnvironment',
'ipDataSetParserService'];
function loadDataService($http, $q, webStoreService, myPrj, dataSetParser) {
var eventMap = [];
var ip_loadDataService = {
getHeadDataSet2: getHeadDataSet2,
requestDataSet: requestDataSet,
updatedDataSet2: updatedDataSet2,
getDataSet2: getDataSet2
};
return ip_loadDataService;
function getHeadDataSet2() {
/*HEAD*/
var deferred = $q.defer();
$http.head(myPrj.URL_DATA)
.success(function (data, status, headers, config) {
var response = [];
response.data = data;
response.headers = headers();
deferred.resolve(response);
//return deferred.promise;
}).error(function (data, status) {
deferred.reject(data);
});
return deferred.promise;
}
function getDataSet2() {
return xhr('get', [myPrj.URL_DATA]);
}
function updatedDataSet2(last_date_modified) {
//var self = this;
var dateOnWebStore = webStoreService.getItem("last-modified");
if (dateOnWebStore === null || Date.parse(dateOnWebStore.date) < Date.parse(last_date_modified))
return true;
return false;
}
function xhr(type, config) {
if (!config && angular.isArray(type)) {
config = type;
type = 'get';
}
var deferred = $q.defer();
$http[type].apply($http, config)
.success(function (data, status, headers, config) {
var response = [];
response.data = data;
response.headers = headers();
deferred.resolve(response);
})
.error(function (error) {
deferred.reject(error);
});
return deferred.promise;
}
}
Answering the question in your second post, maybe you better edit your original post with the new issue you encountered.
If what you are looking for is a way to activate a state (home.myPrjMain in your case) you can do this in various ways:
Using JS - use $state.go(). See - $State documentation
Using directive - use the ui-sref directive with the name of the required state. See - ui-sref documentation
Using regular html href (Navigate to url) - with the full address of the state you need. In your case, "/main".
I hope this was helpful
Have the UI start in an initial loading state then use ui-router to wait for the various pieces to resolve before going to the initial state.
Here is a fiddle showing how it works. Fiddle
I did two parts, one with a single fake service call using timeout and a second with a chained set of calls,.
this.slowServiceCall = function(input, delay) {
var deferred = $q.defer();
var workFinished = function () {
deferred.resolve(input);
};
$timeout(workFinished, delay);
return deferred.promise;
};
this.slowChainedServiceCall = function(input, delay) {
var deferred = $q.defer();
var workFinished = function () {
deferred.resolve(input);
};
$timeout(workFinished, delay);
var promiseChain = deferred.promise.then(function(result) {
var deferred2 = $q.defer();
$timeout(function(){
deferred2.resolve(result + ' Second Piece');
},100);
return deferred2.promise;
});
return promiseChain;
};