2015-09-01 43 views
1

我想获得从工厂到控制器的响应。但是当我从控制器调用工厂的功能时,则控制器不会等待其响应。并给出“未定义”。如何使控制器在angularjs中等待工厂响应?

这里是我的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; 
     }); 

    } 
}; 
+0

你应该使用延期对象(见下文伊格纳特的答案),或至少回调。 – pietro909

回答

1
Do this way 
    In factory 
    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'}      
     }); 

} 

In Controller 
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-路线或UI路由器的最佳方式使用resolve属性

+0

: - 感谢您的帮助。它为我工作。非常感谢 :) – sumitjainjr

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 : 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; 
    }); 
+0

bhaskar: - 如果我使用的是函数,那么我得到错误“TypeError:Can not read property'then'undefined”。 – sumitjainjr

+0

是的,因为你没有返回工厂初始化函数的$ http。 –

2

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

$q documentation

1

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

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

对于promise,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