最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to make the controller wait for factory response in angularjs? - Stack Overflow

programmeradmin1浏览0评论

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
Add a ment  | 

4 Answers 4

Reset to default 2

it'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 value

  • reject(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;   
    }); 
发布评论

评论列表(0)

  1. 暂无评论