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

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

AngularJS 这里是新手。我正在尝试使用服务从 Google 端点获取结果。我启动了 Google API 并且 execute() return 得到了正确的结果。但是,当我尝试将此结果 return 传递给控制器​​中的 $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。我确定我以错误的方式使用了承诺。还是有其他问题?

你必须调用 resolve 和 reject on p.

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;
};

试试这个...

你确实是错误地使用了promise。 API 函数 returns 带有回调,调用回调时需要 resolve 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);
    });

}

那是绝对自然的。 Promises 只是一种让 javascript 异步代码看起来更好的方法 ;) 所以即使使用它们,你仍然必须尊重异步逻辑。

让我解释一下:

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

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

另一点是,当你使用 promise 时,你必须 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 可以绑定 "promises" 而不仅仅是值。

因此,您可以使用:

$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