![](/img/trans.png)
[英]confusion about chaining $q promises with angular and typescript
[英]Angular $q promises and non-linear chaining
大家好 我撞到了砖墙。 我正在尝试研究Angular异步方法调用,promise对象并实现针对特定问题的解决方案。 经过数小时的反复试验和代码重组,我可以确定答案就在我的鼻子底下,但我看不到它。
我有一种情况,必须使用$ http进行后端服务调用,这会产生一个承诺。 在promise的结果中,我将收到一个具有一个字符串属性和100个ID的数组的数据对象。 该后端服务一次仅提供100个ID的有效负载,因此,如该后端服务所提供的那样,我必须进行x个$ http调用才能到达列表的末尾。 根据我对诺言的理解,我必须在诺言的.then()方法中评估$ http响应,如果string属性为'N',那么我知道我必须再次调用后端服务以获得另一批100个ID。 传递完所有ID后,字符串将包含“ Y”,表示已发送完此字符,请勿再次调用。 对此计划无需评论,我知道它相当la脚,不幸的是我无法控制。 ;-)
如果需要更多异步调用,我研究的关于承诺的所有内容似乎都以线性方式说明了承诺链。 无论promise链是嵌套的还是扁平的,似乎我只能发出“已知”或固定数量的顺序调用,例如Promise1到Promise2,Promise3等。请原谅我在Promise方面的有限经验。
这是一个代码示例,您可以看到我卡在这里的位置,向下嵌套。 我不能仅仅希望3、5或10个电话后就“希望”我将获得所有ID。 我需要动态评估每个调用的结果,然后再次调用。
这是调用$ http的Angular服务
(function() {
'use strict';
angular
.module('myapp')
.factory('IDservice', IDservice);
function IDservice($http) {
var service = {
model: {
error: {
state: false,
message: ''
},
ids: [],
end: '',
},
GetIDs: function() {
var request = 'some params...';
var url = 'the url...';
return $http.post(url, request).then(reqComplete).catch(reqFailed);
function reqComplete(response) {
service.model.ids = response.data.idList;
service.model.end = response.data.end;
return service.model;
}
function getIntradayMsrFailed(error) {
service.model.error.state = true;
service.model.error.message = error;
return service.model;
}
}
};
return service;
}
})();
这是调用Angular服务的Controller,它最终在相应的视图上驱动一些UI元素:
(function() {
'use strict';
angular
.module('myapp')
.controller('AvailableIDsController', AvailableIDsController);
function AvailableIDsController($scope, $location, $timeout, IDservice) {
var vm = this;
vm.completeIDList = [];
activate();
function activate() {
IDservice.GetIDs().then(function(response){
vm.completeIDList = response.ids;
console.log('promise1 end');
if(response.end === 'N'){
IDservice.GetIDs().then(function(response){
angular.forEach(response.ids,function(nextID){
vm.comleteIDList.push(nextID);
});
console.log('promise2 end');
if(response.end === 'N'){
IDservice.GetIDs().then(function(response){
angular.forEach(response.ids,function(nextID){
vm.comleteIDList.push(nextID);
});
console.log('promise3 end');
});
}
});
}
});
console.log('mainthread end');
}
}
})();
您可以看到前进的方向……而且非常非常难看。
我需要一种在activate()方法内部的方法来调用一个方法,该方法将负责调用服务调用,并将结果返回到activate()中。 现在,仍然在activate()方法中,评估结果并确定是否再次调用,依此类推。一旦完成主处理线程,我就陷入了困境,在第一个承诺中就剩下了程序控制权。 从那里,您可以执行另一个承诺,等等,然后沿着兔子洞前进。 一旦进入这个陷阱,一切都会丢失。 显然,我没有这样做。 我错过了其他一些简单的难题。 任何建议将不胜感激!
您正在寻找普通的旧递归:
function AvailableIDsController($scope, $location, $timeout, IDservice) {
var vm = this;
vm.completeIDList = [];
return activate(0);
function activate(i) {
return IDservice.GetIDs().then(function(response) {
[].push.apply(vm.completeIDList, response.ids); // simpler than the loop
console.log('promise'+i+' end');
if (response.end === 'N'){
return activate(i+1);
}
});
}
}
不要忘记return
这样promise会链接在一起,您可以等待请求结束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.