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

时间:2015-03-10 07:43:31

标签: javascript angularjs angularjs-scope

AngularJS新手在这里。我正在尝试使用服务从Google端点获取结果。我启动了Google 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。我确信我以错误的方式使用了这个承诺。或者还有其他问题吗?

3 个答案:

答案 0 :(得分:0)

您必须在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;
};

试试这个......

答案 1 :(得分:0)

你确实错误地使用了承诺。 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);
    });

}

答案 2 :(得分:0)

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

让我解释一下:

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

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

另一点是,当您使用承诺时,您必须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

上写了一篇关于此的文章