如何让控制器等待服务返回值以及如何访问控制器中的返回值?

Posted

技术标签:

【中文标题】如何让控制器等待服务返回值以及如何访问控制器中的返回值?【英文标题】:How to make controller wait for service to return a value and how to access the returned value in controller? 【发布时间】:2015-04-18 04:01:30 【问题描述】:

我是 angularjs 的新手。我无法访问 从其控制器中的 angularjs 服务返回的值以下是控制器中的代码:

'use strict';
app.controller('AdminTaskCtrl', function ($scope, Search) 
    $scope.buildEnquiry = function (collegeId, ) 
        Search.getIdByEmail(collegeId).then ( function ( result ) 
            $scope.uId = result;
            console.log($scope.uId);
        );
    ;
);//controller ends here

搜索服务中的代码如下:

'use strict';
           app.factory('Search',function ($firebase, FIREBASE_URL, $rootScope) 
                          var simpleuser = "";
                          getIdByEmail: function(counsellorEmail) 
                          var collegeuserArray = ($firebase(new Firebase(FIREBASE_URL+"abc/def/")).$asArray());
                          collegeuserArray.$loaded(function(collegeuserArray) 
                              for(var i=0; i<collegeuserArray.length; i++) 
                              
                                if((collegeuserArray[i].$value) == counsellorEmail)
                                
                                     simpleuser = collegeuserArray.$keyAt(collegeuserArray[i]);
                                     console.log(simpleuser);
                                     return simpleuser;
                                
                              
                          , function(error) 
                              console.error("Error:", error);
                          );
                    
                  ;     
            );//service ends here.

当代码执行时,它会为 .then 函数提供错误:

TypeError: undefined is not a function 并且控制器中的值未被访问。

请帮忙。

【问题讨论】:

你必须在你的工厂里实现$q,检查这个:docs.angularjs.org/api/ng/service/$q Hey Deblaton Jean-Philippe,我在工厂中实施 $q 时遇到了麻烦。你能指导我完成整个过程吗...!! ? 什么是$firebase,为什么要先退货?你有时会进入你的“for”循环吗? 实际上,firebase 是我的 nosql 数据库,其中包含我需要的一组特定值。我从 firebase 获取值,但问题是我无法在控制器中返回值。控制器中的 [.then] 给出了我在问题中提到的错误。是的,我为从 firebase 获得的每个值输入循环。 执行这个:var something = Search.getIdByEmail(collegeId) 并告诉我something 里面有什么。顺便说一句,我不明白为什么代码在return ($firebase(new Firebase(FIREBASE_URL+"abc/def/")).$asArray()); 之后继续 【参考方案1】:

要直接回答您的问题,$loadedreturns a promise,所以这里最简单的答案是从您的服务中返回它,而不是费心处理 $q 和所有其他事情。

看来这里的整个前提是有缺陷的,这是一个XY problem。似乎有几个黑客旨在颠覆这些库的预期用途,并且像对 Angular walkthrough 和 AngularFire guide 的良好、扎实的阅读一样,在这里可以省去很多痛苦和不必要的复杂性。

这里使用工厂是一种颠覆和高度耦合。语法无效,无法编译。最终,目标是在 AngularFire 返回的同步数组中添加一个搜索方法,这应该使用 $extendFactory 来完成。

app.factory('firebaseRef', function(FIREBASE_URL) 
   return function(path) 
      var ref = new Firebase(FIREBASE_URL);
      if( path )  ref = ref.child(path); 
      return ref;
   
);

app.factory('SearchableArray', function($firebase, $FirebaseArray) 
   var ArrayWithSearch = $FirebaseArray.$extendFactory(
     searchByEmail: function(emailAddress) 
        var res = null;
        for(var i=0, len=this.$list.length; i < len; i++ ) 
           if( this.$list[i].email === emailAddress ) 
              res = this.$list[i];
              break;
           
        
        return res;
     
   );

   return function(ref) 
      return $firebase(ref, arrayFactory: ArrayWithSearch).$asArray();      
   
);

app.controller('Controller', function($scope, SearchableArray, firebaseRef) 
   $scope.data = SearchableArray( firebaseRef('abc/def') );

   $scope.search = function(email) 
      console.log( $scope.data.searchByEmail(email) );
   ;
);

【讨论】:

【参考方案2】:
'use strict';
       app.factory('Search',function ($firebase, FIREBASE_URL, $rootScope, $q) 
                      var simpleuser = "";
                      getIdByEmail: function(counsellorEmail) 
                      var deferred = $q.defer();
                      var collegeUserArray = ($firebase(new Firebase(FIREBASE_URL+"abc/def/")).$asArray());
                      collegeUserArray.$loaded(function(collegeUserArray) 
                          for(var i=0; i<collegeUserArray.length; i++) 
                          
                            if((collegeUserArray[i].$value) == counsellorEmail)
                            
                                 simpleUser = collegeUserArray.$keyAt(collegeUserArray[i]);
                                 console.log(simpleUser);
                                 //return simpleUser;
                                 deferred.resolve(simpleUser);
                            
                          
                      , function(error) 
                          console.error("Error:", error);
                          deferred.reject(error);
                      );
                      return deferred.promise;
                
              ;     
        );

还有你的控制器

'use strict';
app.controller('AdminTaskCtrl', function ($scope, Search) 
  $scope.buildEnquiry = function (collegeId, ) 
    Search.getIdByEmail(collegeId).then ( function ( result ) 
        $scope.uId = result;
        console.log($scope.uId);
    , function(error)
        //If an error happened, handle it here
    );
  ;
);

【讨论】:

感谢 Deblaton Jean-Philippe。该代码对我有用。 这里的语法也显得无效,从原始问题复制而来。此外,$loaded 已经返回了一个承诺。

以上是关于如何让控制器等待服务返回值以及如何访问控制器中的返回值?的主要内容,如果未能解决你的问题,请参考以下文章

webservice 权限控制

如何访问 html5 本地存储 asp.net mvc 3 控制器/管道

异步/等待不等待返回值

Sails.js 控制器等待异步服务方法

Javascript-异步等待并获取-返回值,而不是诺言?

如何在 Java FX 中的 initialize() 方法之前让控制器访问主应用程序?