I am trying to get the response from factory to controller. but when i am calling a function of factory from controller, then the controller not waiting for its response. and giving "undefined".
here it is my controller.js
app.controller('customerCommentsController',function($scope,$http,$stateParams,$sce,$timeout,Comments){
var mentsdata = '';
Comments.init(1,5);
$scope.total_ments = Comments.total();
console.log($scope.total_ments); //undefined
$scope.positive_ments = Comments.positive();
console.log($scope.positive_ments); //undefined
$scopementsdata = Comments.getments(1,30);
console.log($scopementsdata); //undefined
});
here I am calling init() method which gets the response from ajax, which takes some time to execute , but before it could plete, the other 2 statement (total() and positive() method) execute below the init method. and that not gets initialize because of init method not pleted. and that why I am getting undefined. and same problem is ing when I am calling getments method which doesn't wait for its response.
here it is my factory
app.factory("Comments",function($http,$timeout,$q){
var mentshtml = [];
var mentshtml1 = [];
return {
init : function(start,end) {
var request = $http({
method:"post",
url:"/ments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
request.success(function(data){
mentshtml = data;
});
},
total : function() {
return mentshtml.total_ment;
},
positive : function(){
return mentshtml.per_positive_ment;
},
getments : function(start,end) {
var promise = $http({
method:"post",
url:"/ments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
promise.success(function(data){
mentshtml1 = dataments;
console.log(mentshtml1); //giving the object
return mentshtml1;
});
}
};
I am trying to get the response from factory to controller. but when i am calling a function of factory from controller, then the controller not waiting for its response. and giving "undefined".
here it is my controller.js
app.controller('customerCommentsController',function($scope,$http,$stateParams,$sce,$timeout,Comments){
var mentsdata = '';
Comments.init(1,5);
$scope.total_ments = Comments.total();
console.log($scope.total_ments); //undefined
$scope.positive_ments = Comments.positive();
console.log($scope.positive_ments); //undefined
$scope.mentsdata = Comments.getments(1,30);
console.log($scope.mentsdata); //undefined
});
here I am calling init() method which gets the response from ajax, which takes some time to execute , but before it could plete, the other 2 statement (total() and positive() method) execute below the init method. and that not gets initialize because of init method not pleted. and that why I am getting undefined. and same problem is ing when I am calling getments method which doesn't wait for its response.
here it is my factory
app.factory("Comments",function($http,$timeout,$q){
var mentshtml = [];
var mentshtml1 = [];
return {
init : function(start,end) {
var request = $http({
method:"post",
url:"/ments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
request.success(function(data){
mentshtml = data;
});
},
total : function() {
return mentshtml.total_ment;
},
positive : function(){
return mentshtml.per_positive_ment;
},
getments : function(start,end) {
var promise = $http({
method:"post",
url:"/ments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
promise.success(function(data){
mentshtml1 = data.ments;
console.log(mentshtml1); //giving the object
return mentshtml1;
});
}
};
Share
Improve this question
edited Mar 1, 2019 at 13:09
Per Henrik Lausten
21.7k3 gold badges31 silver badges77 bronze badges
asked Sep 1, 2015 at 8:16
sumitjainjrsumitjainjr
7711 gold badge8 silver badges28 bronze badges
1
- you should use a deferred object (see Ignat's answer below) or at least callback. – pietro909 Commented Sep 1, 2015 at 8:33
4 Answers
Reset to default 2it's better to use $q module to work with asynchronous functions in angular. Read this docs:
$q documentation
Do this way:
In factory
return {
init : function(start,end) {
return $http({ //return the promise
method:"post",
url:"/ments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
}
getments : function(start,end) {
return $http({ //return the promise
method:"post",
url:"/ments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
}
In Controller
Comments.init(1,5).then(function(){
$scope.total_ments = Comments.total();
console.log($scope.total_ments);
$scope.positive_ments = Comments.positive();
console.log($scope.positive_ments);
});
Comments.getments(1,30).then(function(data){
$scope.mentsdata =data.ments;
})
Or the best way use resolve property in ng-route or ui-router
You are performing asynchronous request, the problem is that you retrieve data before she is defined.
A good practice is to use promise. You hace to know that the $http service return promises, and has some callback method, like .success()
and .then()
for example.
For promise, angular provide us a pretty good tool : $q.defer().
$q.defer() is a promise manager from the deferred API.
$q.defer()
get 2 methods :
resolve(value)
: which resolve our associated promise, by giving her the final valuereject(reason)
: which resolve an promise error.
So you can do the following :
Controller
(function(){
function Controller($scope, Comments) {
//Retrieve our init promise
var promise_init = Comments.init();
//Retrieve our total promise
var promise_total = Comments.total();
promise_init.then(function(){
//Return promise for chaining
return promise_total;
}).then(function(total){
//Retrieve total of ments
$scope.total = total;
}).catch(function(err){
//Catch error of total ments
$scope.total = err;
});
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
Service
(function(){
function Service($q){
var mentshtml = [];
function init(){
//Create defer object
var defer = $q.defer();
mentshtml = ['a', 'b', 'c'];
//Simulate latency
setTimeout(function(){
//Resolve our promise
defer.resolve();
}, 2000);
//Return a promise
return defer.promise;
}
function total(){
var defer = $q.defer();
mentshtml.length < 3
? defer.reject('error length')
: defer.resolve(mentshtml.length);
return defer.promise;
}
return {
init: init,
total: total
};
}
angular
.module('app')
.factory('Comments', Service);
})();
HTML
<body ng-app='app' ng-controller='ctrl'>
<h2>Total : {{total}}</h2>
</body>
You can see the Working Plunker
Write your all $scope
variable in then
function.
So your Controller.js :
app.controller('customerCommentsController',function($scope,$http,$stateParams,$sce,$timeout,Comments){
var mentsdata = '';
Comments.init(1,5).then(function(){
$scope.total_ments = Comments.total();
console.log($scope.total_ments); //undefined
$scope.positive_ments = Comments.positive();
console.log($scope.positive_ments); //undefined
$scope.mentsdata = Comments.getments(1,30);
console.log($scope.mentsdata); //undefined
}
});
You have to return your $http
request.
So your init function look like :
init : function(start,end) {
return $http({
method:"post",
url:"/ments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
}).success(function(data){
return mentshtml = data;
});
}
And your Factory :
app.factory("Comments",function($http,$timeout,$q){
var mentshtml = [];
var mentshtml1 = [];
return {
init : function(start,end) {
return $http({
method:"post",
url:"/ments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
}).success(function(data){
return mentshtml = data;
});
},
total : function() {
return mentshtml.total_ment;
},
positive : function(){
return mentshtml.per_positive_ment;
},
getments : function(start,end) {
var promise = $http({
method:"post",
url:"/ments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
promise.success(function(data){
mentshtml1 = data.ments;
console.log(mentshtml1); //giving the object
return mentshtml1;
});