Javascript 让angular.forEach在进入下一个对象后等待承诺
我有一个物品清单。对象被传递给延迟函数。我只想在上一次调用解决后,使用下一个对象调用函数。我有什么办法可以做到这一点吗Javascript 让angular.forEach在进入下一个对象后等待承诺,javascript,angularjs,foreach,promise,angular-promise,Javascript,Angularjs,Foreach,Promise,Angular Promise,我有一个物品清单。对象被传递给延迟函数。我只想在上一次调用解决后,使用下一个对象调用函数。我有什么办法可以做到这一点吗 angular.forEach(objects, function (object) { // wait for this to resolve and after that move to next object doSomething(object); }); 检查角度上的$q: function outerFunction() { var defe
angular.forEach(objects, function (object) {
// wait for this to resolve and after that move to next object
doSomething(object);
});
检查角度上的$q:
function outerFunction() {
var defer = $q.defer();
var promises = [];
function lastTask(){
writeSome('finish').then( function(){
defer.resolve();
});
}
angular.forEach( $scope.testArray, function(value){
promises.push(writeSome(value));
});
$q.all(promises).then(lastTask);
return defer;
}
在ES2017和
async/await
(请参阅下面的ES2017中的选项)之前,如果您希望等待承诺,则不能使用.forEach()
,因为承诺没有阻塞。Javascript和承诺就是不能这样工作
async
或Bluebird
这样的库为您排序.forEach()
不能为您提供
下面是一个使用承诺链和角度承诺进行排序的示例(假设
对象是一个数组):
使用标准ES6承诺,这将是:
objects.reduce(function(p, val) {
return p.then(function() {
return doSomething(val);
});
}, Promise.resolve()).then(function(finalResult) {
// done here
}, function(err) {
// error here
});
下面是一个手动排序的示例(假设对象
是一个数组),但这不会像上面的选项那样报告完成或错误:
function run(objects) {
var cntr = 0;
function next() {
if (cntr < objects.length) {
doSomething(objects[cntr++]).then(next);
}
}
next();
}
代码必须包含在async
函数中,然后可以使用wait
告诉解释器在继续循环之前等待承诺解析。注意,虽然这似乎是“阻塞”类型的行为,但它并没有阻塞事件循环。事件循环中的其他事件仍然可以在等待期间处理是您可以使用angular.forEach
来实现这一点
下面是一个示例(假设对象
是一个数组):
下面是如何使用数组来实现这一点。reduce
,类似于@friend00的答案(假设对象
是一个数组):
最简单的方法是创建一个函数,并在解析每个承诺后手动迭代数组中的所有对象
var delayedFORLoop = function (array) {
var defer = $q.defer();
var loop = function (count) {
var item = array[count];
// Example of a promise to wait for
myService.DoCalculation(item).then(function (response) {
}).finally(function () {
// Resolve or continue with loop
if (count === array.length) {
defer.resolve();
} else {
loop(++count);
}
});
}
loop(0); // Start loop
return defer.promise;
}
// To use:
delayedFORLoop(array).then(function(response) {
// Do something
});
我的GitHub上也提供了示例:
这可能会对某些人有所帮助,因为我尝试了上述几种解决方案,然后提出了自己的解决方案,但实际上对我有效(其他解决方案没有)
对我来说就是这样。我不知道这是否是一个正确的方法,但可以帮助减少线
function myFun(){
var deffer = $q.defer();
angular.forEach(array,function(a,i) {
Service.method(a.id).then(function(res) {
console.log(res);
if(i == array.length-1) {
deffer.resolve(res);
}
});
});
return deffer.promise;
}
myFun().then(function(res){
//res here
});
我使用一个简单的解决方案连接到打印机,等待承诺结束后再转到下一个打印机
angular.forEach(object, function(data){
yourFunction(data)
.then(function (){
return;
})
})
在我看来,它可以并行运行所有操作,并使用q.all()
来知道这些操作何时完成。我想OP询问了如何一次一个地对操作进行排序。你的“reduce”解决方案很优雅,但不太管用$q.defer().resolve()
解析承诺,但返回未定义,因此第一个元素的p
未定义。@AgDude-如果您知道建议,请建议对我的答案进行编辑。我没有跟上所有不同的专有promise库(现在有了ES6标准),因此如果这不是创建解析promise ion angularjs来启动链的正确方法,那么我不确定它应该是什么..优雅而干净的解决方案初始值$q.dever().resolve()
对我不起作用(Angular 1.4.3),p
在第一次调用时是未定义的
。但这确实有效:$q(函数(解析){resolve();})
@Artjom-在Angular 1.5.1中,表示.resolve()
返回一个承诺。也许这是在1.4.3之后添加的?无论如何,您的方法也可以正常工作。此外,它还需要是$q.defer().resolve()
-您在评论中的拼写不同。我认为您也可以使用$q.when(true)
。您说得很对!这应该是公认的答案。您可以使用angular.forEach来实现这一点。
objects.reduce(function(p, val) {
// The initial promise object
if(p.then === undefined) {
p.resolve();
p = p.promise;
}
return p.then(function() {
return doSomething(val);
});
}, $q.defer());
var delayedFORLoop = function (array) {
var defer = $q.defer();
var loop = function (count) {
var item = array[count];
// Example of a promise to wait for
myService.DoCalculation(item).then(function (response) {
}).finally(function () {
// Resolve or continue with loop
if (count === array.length) {
defer.resolve();
} else {
loop(++count);
}
});
}
loop(0); // Start loop
return defer.promise;
}
// To use:
delayedFORLoop(array).then(function(response) {
// Do something
});
var sequence;
objects.forEach(function(item) {
if(sequence === undefined){
sequence = doSomethingThatReturnsAPromise(item)
}else{
sequence = sequence.then(function(){
return doSomethingThatReturnsAPromise(item)
});
}
});
function myFun(){
var deffer = $q.defer();
angular.forEach(array,function(a,i) {
Service.method(a.id).then(function(res) {
console.log(res);
if(i == array.length-1) {
deffer.resolve(res);
}
});
});
return deffer.promise;
}
myFun().then(function(res){
//res here
});
angular.forEach(object, function(data){
yourFunction(data)
.then(function (){
return;
})
})