如何使控制器等待angularjs中的工厂响应?

时间:2015-09-01 08:16:29

标签: javascript angularjs angularjs-scope

我正在尝试从工厂到控制器的响应。但是当我从控制器调用工厂的功能时,控制器不等待它的响应。并给予" undefined"。

这是我的controller.js

app.controller('customerCommentsController',function($scope,$http,$stateParams,$sce,$timeout,Comments){     

var commentsdata = '';

Comments.init(1,5);

$scope.total_comments = Comments.total();
console.log($scope.total_comments); //undefined 

$scope.positive_comments = Comments.positive();
console.log($scope.positive_comments);  //undefined 

$scope.commentsdata = Comments.getcomments(1,30);       
console.log($scope.commentsdata);   //undefined     
});

这里我调用init()方法从ajax获取响应,这需要一些时间来执行,但在它完成之前,另外2个语句(total()和positive()方法)在init方法下面执行。并且由于init方法未完成而未初始化。这就是我未定义的原因。     当我调用getcomments方法并不等待它的响应时,同样的问题就出现了。

这是我的工厂

app.factory("Comments",function($http,$timeout,$q){

var commentshtml = [];
var commentshtml1 = [];

return {
    init :  function(start,end) {  
    var request = $http({   
            method:"post",
            url:"/comments.php",
            data: {start:start,end:end},                
            headers: {'Content-Type' : 'application/x-www-form-urlencoded'}                     
        });     

    request.success(function(data){                 
            commentshtml = data;            
        });             
    },      
    total : function() {

                return commentshtml.total_comment;                    
    },
    positive : function(){

            return commentshtml.per_positive_comment;               
    },
    getcomments : function(start,end) { 

        var promise  = $http({  
            method:"post",
            url:"/comments.php",
            data: {start:start,end:end},                
            headers: {'Content-Type' : 'application/x-www-form-urlencoded'}                     
        });

        promise.success(function(data){                 
            commentshtml1 = data.comments;
            console.log(commentshtml1); //giving the object             
            return commentshtml1;   
        }); 

    }
};

4 个答案:

答案 0 :(得分:2)

最好使用$ q模块处理角度异步函数。阅读本文档:

$q documentation

答案 1 :(得分:1)

这样做:

在工厂

   return {
    init :  function(start,end) {  
     return $http({     //return the promise 
            method:"post",
            url:"/comments.php",
            data: {start:start,end:end},                
            headers: {'Content-Type' : 'application/x-www-form-urlencoded'}                     
        });     
    }
  getcomments : function(start,end) { 
             return $http({   //return the promise
            method:"post",
            url:"/comments.php",
            data: {start:start,end:end},                
            headers: {'Content-Type' : 'application/x-www-form-urlencoded'}                     
        });

}

在控制器

Comments.init(1,5).then(function(){
 $scope.total_comments = Comments.total();
console.log($scope.total_comments);  

  $scope.positive_comments = Comments.positive();
console.log($scope.positive_comments);
 });
Comments.getcomments(1,30).then(function(data){
  $scope.commentsdata =data.comments;

})

或者在ng-route或ui-router

中使用resolve属性的最佳方式

答案 2 :(得分:1)

您正在执行异步请求,问题是您在定义数据之前检索数据。

一个好的做法是使用承诺。您需要知道 $ http 服务返回承诺,并且有一些回调方法,例如.success().then()

对于诺言,angular为我们提供了一个非常好的工具: $ q.defer()

$ q.defer()是来自延期API 承诺管理器

$q.defer()获得2种方法:

  • resolve(value):通过向她提供最终价值来解决我们的相关承诺

  • reject(reason):解决了承诺错误。

所以你可以做到以下几点:

<强>控制器

(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 comments
    $scope.total = total;
  }).catch(function(err){
    //Catch error of total comments
    $scope.total = err;
  });

}

angular
.module('app', [])
.controller('ctrl', Controller);

})();

<强>服务

(function(){

  function Service($q){

    var commentshtml = [];

    function init(){
      //Create defer object
      var defer = $q.defer();
      commentshtml = ['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();
      commentshtml.length < 3
      ? defer.reject('error length')
      : defer.resolve(commentshtml.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>

您可以看到Working Plunker

答案 3 :(得分:0)

$scope函数中写下您的所有then变量。

所以 Controller.js

app.controller('customerCommentsController',function($scope,$http,$stateParams,$sce,$timeout,Comments){     

    var commentsdata = '';

    Comments.init(1,5).then(function(){

         $scope.total_comments = Comments.total();
         console.log($scope.total_comments); //undefined 

         $scope.positive_comments = Comments.positive();
         console.log($scope.positive_comments);  //undefined 

         $scope.commentsdata = Comments.getcomments(1,30);       
         console.log($scope.commentsdata);   //undefined     
    }
});

您必须退回$http请求。

所以你的init函数看起来像:

init : function(start,end) {  
return $http({   
        method:"post",
        url:"/comments.php",
        data: {start:start,end:end},                
        headers: {'Content-Type' : 'application/x-www-form-urlencoded'}                     
    }).success(function(data){
          return commentshtml = data;
    });
}

和你的工厂:

app.factory("Comments",function($http,$timeout,$q){

var commentshtml = [];
var commentshtml1 = [];

return {
init :  function(start,end) {  
return $http({   
        method:"post",
        url:"/comments.php",
        data: {start:start,end:end},                
        headers: {'Content-Type' : 'application/x-www-form-urlencoded'}                     
    }).success(function(data){
          return commentshtml = data;
    });
},      
total : function() {

            return commentshtml.total_comment;                    
},
positive : function(){

        return commentshtml.per_positive_comment;               
},
getcomments : function(start,end) { 

    var promise  = $http({  
        method:"post",
        url:"/comments.php",
        data: {start:start,end:end},                
        headers: {'Content-Type' : 'application/x-www-form-urlencoded'}                     
    });

    promise.success(function(data){                 
        commentshtml1 = data.comments;
        console.log(commentshtml1); //giving the object             
        return commentshtml1;   
    });