从服务返回值时$scope控制器的变量是未定义的

$scope variable of a controller is undefined when returning values from a service

本文关键字:变量 未定义 控制器 scope 服务 返回值      更新时间:2023-09-26

AngularJS新手在这里。我正在尝试使用服务从谷歌端点获取结果。我已经启动了谷歌API,execute()返回正确的结果。但是当我尝试将此结果返回到控制器中的$scope变量时,$scope变量仍未定义。

服务中的函数如下所示:

app.service('gapiService',function(){

var getSubjectList=function(){
            gapi.client.subjectendpoint.listSubject().execute(function(resp){
        if(!resp.code){
            console.log("resp "+resp.items); //this prints the proper result
            return resp.items;

        }
    });
};

return{
    getSubjectList:getSubjectList
};
});
控制器中调用

服务中函数的函数如下所示:

var getSubjectList=function(){
    $scope.subj=gapiService.getSubjectList();
    console.log($scope.subj); //this is undefined
}

此外,控制器中的 console.log() 在服务中的 console.log() 之前打印。所以我尝试使用 promise 并像这样更改服务:

var getSubjectList=function(){
  var p=$q.defer();
            gapi.client.subjectendpoint.listSubject().execute(function(resp){
        if(!resp.code){
            console.log("resp "+resp.items);
            return resp.items;

        }
    });
   return p.promise;
};

即使这样,我也不会将 resp.items 放入我的 $scope.subj 中。我确定我以错误的方式使用了这个承诺。还是还有其他问题?

这是绝对自然的。承诺只是使javascript异步代码看起来更好的一种方式;)因此,即使使用它们,您仍然必须尊重异步逻辑。

让我解释一下:

当您在控制器中调用 getSubjectList 时,它将执行将调用gapi.client.subjectendpoint.listSubject().execute() gapiService.getSubjectList()但请注意,您在服务中登录到控制台的函数是回调,因此将在当前控制器的代码完成后稍后调用它。

这就是控制器在服务回调之前继续执行和记录的原因。

另一点是,当你使用承诺时,你必须resolvereject(如果某些东西失败了),你的服务代码应该看起来像这样:

var getSubjectList = function () {
 var deferred = $q.defer();
 gapi.client.subjectendpoint.listSubject().execute(function(resp){
   if(!resp.code){
     deferred.resolve(resp.items);
   }
   else {
     deferred.reject("OH MY GOD! SOMETHING WENT WRONG!")
   }
 });
 return deferred.promise;
};

控制器的代码应为:

var getSubjectList=function(){
    gapiService.getSubjectList().then(function (items) {
      $scope.subj = items;
    });
  }

如您所见,现在是异步的,因为使用 then ,您正在等待解决承诺,以便调用将值设置到范围内的回调。

顺便说一下,AngularJS可以绑定"承诺",而不仅仅是价值。

因此,您可以使用:

$scope.subj = gapiService.getSubjectList();

如果您尝试console.log($scope.subj),它只会向您显示尚未包含该值的承诺,但是如果您在模板中像这样使用它:

<ul ng-repeat="item in $scope.subj">
    <li ng-bind="item"></li>
</ul>

Angular 将监视承诺,直到它被解决,然后使用解析的值。

不要忘记使用promise.catch处理错误和类似的事情 和promise.finally.

为了性能起见,如果您的值在设置后没有更改,请使用 AngularJS 1.3 的一次性绑定。

<ul ng-repeat="item in ::$scope.subj">
    <li ng-bind="::item"></li>
</ul>

我们在博客上写了一篇关于此的文章 www.blog.wishtack.com

你必须在 p 上调用 resolve 和拒绝。

var getSubjectList=function(){
  var p=$q.defer();
            gapi.client.subjectendpoint.listSubject().execute(function(resp){
        if(!resp.code){
            console.log("resp "+resp.items);
            p.resolve(resp.items);
        }
       p.reject('error');
    });
   return p.promise;
};

试试这个...

你确实错误地使用了承诺。API 函数返回回调,调用回调时需要解析 promise。应按以下方式完成:

var getSubjectList=function(){
  var p=$q.defer();
  gapi.client.subjectendpoint.listSubject().execute(function(resp){
      if(!resp.code){
          console.log("resp "+resp.items);
          p.resolve(resp.items);

        }
        p.reject();
    });
   return p.promise;
};

您可以使用承诺中的"then"函数来获取已解决的承诺:

var getSubjectList=function(){
    gapiService.getSubjectList().then(function(result){
        $scope.subj=result;
        console.log($scope.subj);
    });
}