2016-08-13 67 views
0

在AngularJS中,我似乎无法理解'promise'的概念,我使用restangular库通过REST获取资源,但是我总是得到空结果。下面的代码在angularjs中使用延迟结果

.service('CareersService', [ 'Restangular', '$sce', function(Restangular, $sce){ 
      var vacancies = []; 
      var result; 
      this.getVacancies = function() { 
       Restangular.all('job_posts').getList({active: 'true'}).then(function(job_posts){ 
       job_posts.forEach(function(job_post){ 
        vacancies.push(_.pick(job_post,['id','title','min_experience','max_experience','location'])); 
       }) 
      }) 
      return vacancies; 
      } 
      this.getVacancy = function(job_id){ 
        Restangular.one('job_posts',job_id).get().then(function(job_post){ 
        result = _.pick(job_post, 'title','min_experience','max_experience','location','employment_type','description'); 
        var safe_description = $sce.trustAsHtml(result.description); 
         var emp_type = _.capitalize(result.employment_type); 
         _.set(result, 'description', safe_description); 
         _.set(result, 'employment_type', emp_type); 
      }); 
       return result;    
      } 
    }]).controller('DetailsCtrl', ['$scope' ,'$stateParams', 'CareersService' ,function($scope, $stateParams, CareersService) { 

      $scope.data.vacancy = { title: 'Loading ...', contents: '' }; 

      $scope.data.vacancy = CareersService.getVacancy($stateParams.job_id); 

}]) 

,然后在视图

<div class="container"> 
    <a ui-sref="careers" class="btn btn-primary">Show All</a> 
    <div class="row"> 
     <h2>{{ data.vacancy.title }}</h2> 
     <p>{{ data.vacancy.min_experience }}</p> 
     <p>{{ data.vacancy.max_experience }}</p> 
     <p>{{ data.vacancy.location }}</p> 
     <p>{{ data.vacancy.employment_type }}</p> 
     <p ng-bind-html="data.vacancy.description"></p>  
    </div> 
</div> 

我缺少的东西在使用承诺的方式?


更新

这里是更新的代码感谢我来到这里的所有帮助,

  this.getVacancies = function() { 
       Restangular.all('job_posts').getList({active: 'true'}).then(function(job_posts){ 
       job_posts.forEach(function(job_post){ 
        vacancies.push(_.pick(job_post,['id','title','min_experience','max_experience','location'])); 
       }) 
       return vacancies; 
      }) 
      } 
     this.getVacancy = function(job_id){ 
        Restangular.one('job_posts',job_id).get().then(function(job_post){ 
        vacancy = _.pick(job_post, 'title','min_experience','max_experience','location','employment_type','description'); 
        ... 
        return vacancy; 
      }); 
      } 
}]) 

并在控制器

CareersService.getVacancy($stateParams.job_id).then(function (vacancy){ 
      $scope.data.vacancy = vacancy; 
      }); 

CareersService.getVacancies().then(function (vacancies){ 
     $scope.data.vacancies = vacancies; 
    }); 

我现在得到的错误

Cannot read property 'then' of undefined

在生产线

CareersService.getVacancies().then(function(vacancies) { 
+0

你注销了什么空缺包含?并且还让你感到沮丧并检查你是否获得了服务中的数据? –

+0

有一个对服务的调用,并且成功(现在是304)响应,所以数据肯定被填充到job_post中。不知道为什么结果没有被填充。未定义它表示当我在返回之前登录到控制台时。对于JS和Angular来说,这是一个不错的选择,所以甚至无法找出一个好的失败测试,​​否则也会分享这个测试 –

+1

''return'vacancies/result' ** **之前** .then()调用:[为什么我的变量在函数内部修改后没有改变? - 异步代码引用](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Andreas

回答

1

Restangular使得在HTTP API调用,一旦拨打电话返回底层承诺目的。并且它的功能在.then中可以得到API响应的数据。

所以在这里你正在一个异步调用,并考虑它的出现它同步的方式一样,你可以看到你已经从Restangular调用返回result/vacancies阵列,以这种方式result/vacancies总是要为空。

在这种情况下,您应该从服务方法返回承诺。并从承诺中返回适当的格式化数据,以便您可以在控制器中承诺(通过检索数据)chain

服务

this.getVacancies = function() { 
    //returned Restangular promise 
    return Restangular.all('job_posts').getList({ 
    active: 'true' 
    }).then(function(job_posts) { 
    job_posts.forEach(function(job_post) { 
     vacancies.push(_.pick(job_post, ['id', 'title', 'min_experience', 'max_experience', 'location'])); 
    }); 
    //return calculated result 
    return vacancies; 
    }) 
} 
this.getVacancy = function(job_id) { 
    //returned Restangular promise 
    return Restangular.one('job_posts', job_id).get().then(function(job_post) { 
    result = _.pick(job_post, 'title', 'min_experience', 'max_experience', 'location', 'employment_type', 'description'); 
    var safe_description = $sce.trustAsHtml(result.description); 
    var emp_type = _.capitalize(result.employment_type); 
    _.set(result, 'description', safe_description); 
    _.set(result, 'employment_type', emp_type); 
    //returned result to chain promise 
    return result; 
    }); 
} 

正如我说,现在你可以很容易地内控制器链的承诺具有在服务方法调用.then功能。

CareersService.getVacancy($stateParams.job_id).then(function(result){ 
    $scope.data.vacancy = result; 
}); 

更新

没有.then语法的工作,但你需要一个方法调用之后加入.$object做小的变化了。

$scope.data.vacancy = CareersService.getVacancy($stateParams.job_id).$object; 

$object是承诺对象内加入由Restangular属性。在进行API调用时,当时它将$scope.data.vacancy的值作为空数组([]),并且一旦服务器响应并响应,它就会用服务器收到的响应填充该对象。在幕后它只更新$object属性的值,该值自动更新$scope.data.vacancy的值。

$resourcengResource中存在相同的行为。


我想也承认,当你链接承诺时,你必须明确处理错误情况。而在目前的代码中,你没有处理这种失败情况。所以我建议你也可以通过在Restangular REST API调用中加入error函数来达到这个目的。并使用$q.reject('My error data, this can be object as well')

+0

好吧,所以基本上'$ scope.data.vacancy = CareersService.getVacancy($ stateParams.job_id);'''或$ scope.data.vacancies = CareersService.getVacancies ();'不用等待结果填充就执行?我以为因为我处理结果,然后阻止服务,情况并非如此。 –

+0

值得注意的是,'$ scope.data.vacancies = CareersService.getVacancies();'最终会渲染带有第一批中获取的列表空位的索引视图,所以仍然有点混乱。 –

+0

@AnadiMisra你在这里,我也加了解释。 –

0

您正在进行异步调用以获取结果。所以你需要一个回调或promise来处理这个问题。用最少的代码改变一个选择是让服务来回报承诺,并在控制器通过then

.service('CareersService', ['Restangular', '$sce', function(Restangular, $sce) { 
    var vacancies = []; 
    var result; 
    this.getVacancies = function() { 
    Restangular.all('job_posts').getList({ 
     active: 'true' 
    }).then(function(job_posts) { 
     job_posts.forEach(function(job_post) { 
     vacancies.push(_.pick(job_post, ['id', 'title', 'min_experience', 'max_experience', 'location'])); 
     }) 
    }) 
    return vacancies; 
    } 
    this.getVacancy = function(job_id) { 
    return Restangular.one('job_posts', job_id).get().then(function(job_post) { 
     result = _.pick(job_post, 'title', 'min_experience', 'max_experience', 'location', 'employment_type', 'description'); 
     var safe_description = $sce.trustAsHtml(result.description); 
     var emp_type = _.capitalize(result.employment_type); 
     _.set(result, 'description', safe_description); 
     _.set(result, 'employment_type', emp_type); 
     return result; 
    }); 
    } 
}]).controller('DetailsCtrl', ['$scope', '$stateParams', 'CareersService', function($scope, $stateParams, CareersService) { 

    $scope.data.vacancy = { 
    title: 'Loading ...', 
    contents: '' 
    }; 

    CareersService.getVacancy($stateParams.job_id).then(function(result) { 
    $scope.data.vacancy = result; 
    }); 

}]) 
0

得到的结果你的话外做回尝试中移动它,然后运作

this.getVacancies = function() { 

      Restangular.all('job_posts').getList({active: 'true'}).then(function(job_posts){ 
      job_posts.forEach(function(job_post){ 
       vacancies.push(_.pick(job_post,['id','title','min_experience','max_experience','location'])); 
      }) 
      return vacancies; 
     })   
     }