在 angularjs 中处理延迟结果
working with deferred results in angularjs
我似乎无法理解 AngularJS 中 'promise' 的概念,我正在使用 restangular 库通过 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);
}])
然后在视图中
<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>
我是不是在使用 promises 的过程中遗漏了什么?
更新
这是更新后的代码,感谢我在这里得到的所有帮助,
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) {
Restangular 通过 http 进行 API 调用,一旦它进行调用,它就会成为 return 的底层承诺对象。在它的 .then
函数中你可以得到 API 响应的数据。
所以你在这里进行异步调用并考虑它以同步方式发生,就像你可以看到你有 returned result
/vacancies
array from Restangular
调用,这样 result
/vacancies
总是空的。
在这种情况下,您应该 return 来自服务方法的承诺。 return 来自 promise 的适当格式化数据,以便您也可以 chain
在控制器中实现该 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
函数来轻松地在控制器内部链接承诺。
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('My error data, this can be object as well')
.
您正在进行异步调用以获取结果。所以你需要一个回调或 promise 来处理这个。代码更改最少的一种选择是使服务成为 return 承诺,并在控制器中通过 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;
});
}])
你在外面做 return 然后试着把它移到里面然后函数
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;
})
}
我似乎无法理解 AngularJS 中 'promise' 的概念,我正在使用 restangular 库通过 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);
}])
然后在视图中
<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>
我是不是在使用 promises 的过程中遗漏了什么?
更新
这是更新后的代码,感谢我在这里得到的所有帮助,
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) {
Restangular 通过 http 进行 API 调用,一旦它进行调用,它就会成为 return 的底层承诺对象。在它的 .then
函数中你可以得到 API 响应的数据。
所以你在这里进行异步调用并考虑它以同步方式发生,就像你可以看到你有 returned result
/vacancies
array from Restangular
调用,这样 result
/vacancies
总是空的。
在这种情况下,您应该 return 来自服务方法的承诺。 return 来自 promise 的适当格式化数据,以便您也可以 chain
在控制器中实现该 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
函数来轻松地在控制器内部链接承诺。
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('My error data, this can be object as well')
.
您正在进行异步调用以获取结果。所以你需要一个回调或 promise 来处理这个。代码更改最少的一种选择是使服务成为 return 承诺,并在控制器中通过 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;
});
}])
你在外面做 return 然后试着把它移到里面然后函数
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;
})
}