javascript - 在 AngularJS 中使用延迟结果

标签 javascript angularjs angular-promise restangular

我似乎无法理解 AngularJS 中“ promise ”的概念,我正在使用 RESTANGLE 库通过 REST 获取资源,但是我总是得到空结果。这是代码

.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);

}])

然后在 View 中

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

我在使用 Promise 的过程中是否遗漏了一些东西?

<小时/>

更新

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

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

在 Controller 中

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

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

我现在收到错误

无法读取未定义的属性“then”

在线

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

最佳答案

Restangular 通过 http 进行 API 调用,一旦调用,它就会返回底层的 Promise 对象。在其.then函数中可以获取API响应的数据。

因此,您在这里进行异步调用,并认为它以同步方式发生,就像您可以看到您从 Restangular 返回了 result/vacancies 数组一样 调用,这样 result/vacancies 始终为空。

在这种情况下,您应该从服务方法返回一个 promise 。并从 Promise 返回适当的格式化数据,以便您也可以在 Controller 中链接该 Promise(通过检索数据)。

服务

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 函数轻松地在 Controller 内链接 Promise。

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 添加到 Promise 对象内部的属性。在进行 API 调用时,它会将 $scope.data.vacancy 值设置为空白数组 ([]),一旦服务器响应响应,它就会填充该值服务器收到响应的对象。在后台,它仅更新 $object 属性的值,该属性会自动更新 $scope.data.vacancy 值。

ngResource$resource 中也有相同的行为。

<小时/>

我还想指出,当您链接 Promise 时,您必须显式处理错误情况。而在当前代码中,您还没有处理这种失败情况。因此,我建议您也通过在 Restangular REST API 调用中添加 error 函数来实现这一点。并使用 $q.reject('我的错误数据,这也可以是对象')

关于javascript - 在 AngularJS 中使用延迟结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38934419/

相关文章:

javascript - 使用带有 ng-repeat 的函数会导致无限摘要循环

javascript - 如果高度超过 225px,Video.js 黑屏仅播放音频

javascript - 如何转换 "timestamp_usec"?

javascript - 使用 Angularjs 在 json 文件中搜索和过滤字典

javascript - 如何开始编写像 mohiomap 这样的东西?

javascript - AngularJS:具有 promise 和非 promise 数据的功能

javascript - Vis.js 修复了大规模大图中节点渲染不正确的问题

javascript - Electron/浏览器 : Detect when the app is opened again from taskbar (after being minimized)

html - 强制带有图标的跨度与前面的跨度换行

angularjs - 如何从基于回调的 API 创建 AngularJS Promise