在第二次方法完成之前,范围不被设置

时间:2015-03-29 19:20:16

标签: javascript angularjs

我在我的范围内设置属性时出现问题。它确实设置但仅在第二次我点击与我的控制器绑定的按钮之后。

app.controller('ContactsController',  ['$scope','$window','$http','googleService', function($scope, $window, $http, googleService) {

 $scope.login = function () {
  var emails =[];
  var promise =  googleService.login()
      promise.then(function (data) {
        console.log(data[0]);
        gapi.client.load('gmail', 'v1', function() {
            var request = gapi.client.gmail.users.messages.list({'userId' :'me',
            labelIds: ['INBOX'],
            });
            request.execute(function(resp) {
            $scope.emails  = googleService.makeEmails(resp);             
            });
        });                                                                                 
       }

      , function (err) {
        console.log('Failed: ' + err);

      });   
   };
}]);

这是我的服务方法。

this.makeEmails = function(resp){
 var factory = [];
    angular.forEach(resp.messages, function(message){
            var newEmail = gapi.client.gmail.users.messages.get({'userId': 'me','id': message.id ,'format':'metadata', 'metadataHeaders': ['subject','from','to','date']});
                newEmail.execute(function(resp) {
                    var emailw = resp;

                    factory.push(emailw);
                });
        });
        return factory;
 }

所以我单击与控制器中的click()方法绑定的按钮,在网络选项卡中,我看到所有响应都通过,当我逐步完成代码工厂时。我无法弄清楚为什么第一次点击范围没有设置但第二次点击设置它。

2 个答案:

答案 0 :(得分:2)

你必须使用$ q

来使用promise / deferred模式

https://docs.angularjs.org/api/ng/service/$q

类似这样的事情

//service
this.makeEmails = function (resp) {
    //create a deferred/ promise object
    var deferred = $q.defer();
    var tasks = [];

    //create an array of promises
    angular.forEach(resp.messages, function (message) {
        tasks.push(function () {
            var deferred = $q.defer();
            var newEmail = gapi.client.gmail.users.messages.get({
                'userId': 'me',
                'id': message.id,
                'format': 'metadata',
                'metadataHeaders': ['subject', 'from', 'to', 'date']
            });
            newEmail.execute(function (resp) {
                deferred.resolve(resp);
            });
        });
    });

    //return the result when all the promises get executed
    $q.all(tasks).then(function(result){
        deferred.resolve(result);
    })
    return deferred;
};

//controller
googleService.makeEmails(resp).then(function(result){
    $scope.emails = result;
});

答案 1 :(得分:2)

需要注意的重要事项:此处接受的答案是使用一种名为deferred antipattern的气馁做法。您应该避免这样做,因为它会导致无法正确处理错误的详细代码。

我强烈建议您使用以下方法,该方法更清晰,更强大:

//service
this.makeEmails = function (resp) {
    var promises = resp.messages.map(function (message) {
        return $q(function (resolve) {
            gapi.client.gmail.users.messages.get({
                'userId': 'me',
                'id': message.id,
                'format': 'metadata',
                'metadataHeaders': ['subject', 'from', 'to', 'date']
            }).execute(resolve);
        });
    });

    return $q.all(promises);    
};

//controller
googleService.makeEmails(resp).then(function(result){
    $scope.emails = result;
});