访问数组中承诺的值
Accessing values of promises in an array
我正在尝试从http请求创建一个数组,该数组包含一个name属性和两个承诺:一个作为数组,另一个作为对象。我能够使用这种方法获取我需要的信息,但我无法访问它以在 html 范围内显示它。例如,当我注销数组时,"people"我得到一个对象数组(看起来像:[Object,Object,Object]),我必须展开一堆东西才能看到每个对象的实际值,这样"person.skills"实际上必须是"person.skills.$$state.value"。此外,在页面上,将显示 {{person.name}},但其他两个只是空对象,如下所示:{}。那么我如何访问承诺的值,以便我可以只使用 {{person.skills}} 来显示数组呢?
.js
var getPeople = function() {
var named = $q.defer();
$http.get('/getnames').success(function (response) {
named.resolve(response);
});
return named.promise;
};
getPeople().then(function(namesRes) {
var people = [];
names = namesRes;
names.forEach(function(index){
var name = index;
var count = $q.defer();
var skills = $q.defer();
var urls = '/getskillsbyname/' + name;
var urlc = '/getcountbyname/' + name;
$http.get(urls).success(function (response) {
skills.resolve(response);
});
$http.get(urlc).success(function (response) {
count.resolve(response);
});
people.push({name:name, skills:skills.promise, count:count.promise});
});
return people;
}).then(function(people) {
console.log(people);
$scope.people = people;
});
.html
<div ng-repeat="person in people">
<p>{{person.name}}</p>
<p>{{person.skills}}</p>
<p>{{person.count}}</p>
</div>
您的方法未正确返回 promise,您需要使用 $q
来等待所有内部承诺完成。
我已经通过在 forEach
循环中维护 grand promise 变量来实现您的代码,每当询问skills
并发出couts
调用时,它都会将该调用放入$q.all
,并且$q.all
承诺被移动到grandPromiseArray
。
var getPeople = function() {
return $http.get('/getnames');
};
getPeople().then(function(response) {
var people = [];
names = response.data;
grandPromiseArray = [];
names.forEach(function(index) {
var name = index, count = $q.defer(), skills = [],
urls = '/getskillsbyname/' + name, urlc = '/getcountbyname/' + name;
grandPromiseArray.push(
$q.all([$http.get(urls), $http.get(urlc)])
.then(function(response) {
people.push({
name: name,
skills: response[0].data, //response[0] value returned by 1st promise
count: response[1].data //response[1] value returned by 2nd promise
});
})
);
});
return $q.all(grandPromiseArray).then(function() {
return people
});
})
.then(function(people) {
console.log(people);
$scope.people = people;
});
有效承诺链的示例:
function getSomeData(){
var defer = $q.defer();
$http.get(urls).success(function (response) {
defer.resolve(response);
});
return defer.promise;
}
然后,您可以访问承诺数据,例如:
getSomeData().then(function(data){
console.log(data); // This is the response of the $http request
});
在函数中组织您的请求,它看起来更干净。
默认情况下,$http也返回 promise,但我建议创建一个服务/工厂,它执行您的请求,然后您需要延迟。
$http.get(urls).then(function(data){
});
承诺不会自动允许您在 Angular 中显示结果。
Promise 是一个对象,它允许您通过传入最终触发并传递值的函数将异步操作链接在一起。
你不能要求myPromise.value
并期望它在那里,因为这是一个异步过程,可能需要 20 毫秒、2 分钟,或者可能永远不会回来。
就其结构而言,如果您将数据获取部分分解到服务中,并且只是将服务注入控制器,则可能会更清晰,更容易推理。
我不确定你一直在使用哪个版本的 Angular,但我希望它至少是 1.2。
另外,我的例子是使用本机 Promise 构造函数,但我确信 Angular 的 $q 版本现在拥有所需的一切,如果您不使用 promise polyfill。
function PersonService (http) {
function getResponseData (response) { return response.data; }
function getURL (url) { return http.get(url).then(getResponseData); }
function makePerson (personData) {
return {
name: personData[0],
skills: personData[1],
count: personData[2]
};
}
var personService = {
getNames: function () { return getURL("/names/"); },
getSkills: function (name) { return getURL("/getskillsbyname/" + name); },
getCounts: function (name) { return getURL("/getcountsbyname/" + name); },
loadPerson: function (name) {
return Promise.all([
Promise.resolve(name),
personService.getSkills(name),
personService.getCount(name)
]).then(makePerson);
},
loadPeople: function (names) {
return Promise.all(names.map(personService.loadPerson));
}
};
return personService;
}
以下是我的人员服务可能的样子。
我编写了几个不断被重用的超小辅助函数。然后,我使服务完全是为了获取人员或有关人员的详细信息。
我正在使用Promise.all
,并传递给它一系列承诺。当数组中的每个承诺都完成后,它会返回一个由承诺返回的所有数据的数组。 Promise.resolve
用于一个地方。它基本上返回一个自动成功的承诺,以及它被赋予的值。当你需要一个承诺来启动一个链时,这使得它非常有用,但除了返回你已经拥有的值之外,你不必做任何特别的事情。我的假设是,q
现在以与规范相同的方式命名其方法,并且 Angular 的$q
实现也遵循规范。
function MyController (personService) {
var controller = this;
controller.people = [];
controller.error = false;
init();
function setPeople (people) {
controller.people = people || [];
}
function handleError (err) {
setPeople([]);
controller.error = true;
}
function init () {
return personService.getNames()
.then(personService.loadPeople)
.then(setPeople)
.catch(handleError);
}
}
我的控制器现在变得非常非常简单。它使用服务来获取姓名并加载人员,然后设置他们,就可以使用了。 如果有错误,我会以任何有意义的方式处理它。
处理这些东西的注入非常快速和简单:
angular.module("myExample")
.service("PersonService", ["$http", PersonService])
.controller("MyController", ["PersonService", MyController]);
在页面上使用它现在也是无痛的:
<div ng-controller="MyController as widget">
<ul ng-hide="widget.people.length == 0">
<li ng-repeat="person in widget.people">
<person-details person="person"></person-details>
</li>
</ul>
<div ng-show="widget.error">Sorry, there was an error with your search.</div>
</div>
我认为您可以使用$q.all
来构建您的人员:
var p = $q.all({
name: $q.when(name),
skills: $http.get(urls),
count: $http.get(urlc)
});
p.then(function(person) {
people.push(person);
});
$q.all
将构造一个新的承诺,当所有输入承诺解析时,该承诺将得到解析。 由于我们输入了一个地图,$q.all
将使用具有相同键的地图进行解析。 这些值是相应承诺的决议。 在这种情况下,这是一个人,所以我们可以直接将其推送到 People 数组中。
这是一个有点幼稚的实现。 由于调用是异步的,因此不能保证名称的顺序将保留在人员中 - 但如果它很重要,您应该不会太难解决这个问题。
和技能的所有承诺的数组。已将这些请求分解为自己的函数以提高可读性
此外,$http
then()
返回一个具有属性data
的 promise 对象
var getPeople = function() {
return $http.get('/getnames').then(function(response) {
return response.data;
});
};
getPeople().then(function(people) {
var promises = [];
people.forEach(function(person) {
// push new requests to promise array
promises.push(getSkills(person));
promises.push(getCount(person))
});
// when all promises resolved return `people`
return $q.all(promises).then(function() {
// return `people` to next `then()`
return people;
});
}).then(function(people) {
console.log(people);
$scope.people = people;
}).catch(function(){
// do something if anything gets rejected
});
function getCount(person) {
var urlc = '/getcountbyname/' + person.name;
return $http.get(urlc).then(function(response) {
person.count = response.data
});
}
function getSkills(person) {
var urls = '/getskillsbyname/' + person.name;
return $http.get(urls).then(function(response) {
person.skills = response.data
});
}
- Bluebird中承诺链数组的串行执行
- 如何按顺序执行承诺数组
- 角度 - 数组从承诺更新,整数不更新
- 链承诺.all 与从上一个承诺返回的数组.all.
- 链接返回承诺数组的函数
- 如何使用 Parse.promise javascript 定义一个承诺数组并获取结果数组 [parse.com]
- 实现时,将承诺数组转换为值数组
- Q.承诺数组,如果满足1个以上,则发出警报
- Node js没有解析承诺数组
- Emberjs拆分承诺数组
- 在AngularJS中向承诺数组中添加一个项
- 我如何从forEach循环中实现一个扁平的承诺数组?
- 动态推入$q.all()承诺数组
- 获取承诺数组的大小(量角器)
- 试图发送angular动态承诺数组来表示服务器
- 在承诺数组之间添加延迟
- 如何构造一个jquery承诺数组
- 用Angular UI Router解析承诺数组
- js承诺数组
- 使用'all'承诺数组上的聚合函数