我试图使用$ q.all等待所有承诺得到解决但在第一次承诺完成后调用它!
我做错了什么?
function sendAudits(audits) {
var promises = [];
$scope.sendAudits = {
progress: 0
};
angular.forEach(audits, function (audit, idAudit) {
promises.push(saveAudit(audit));
});
$q
.all(promises)
.then(function (data) {
console.log(data);
}, function (errors) {
console.log(errors);
});
}
function saveAudit(audit) {
var filename = audit.header.id + ".txt";
return $http({
method: 'PUT',
url: '/audits/audits.php?filename=' + encodeURIComponent(filename),
data: AuditSvc.getPlainAudit(audit.header.id)
}).finally(function () {
$scope.sendAudits.progress += 1;
console.log("FINALLY: " + audit.header.id);
});
}
修改
更深入地分析问题,当某些响应出错时会出现这种情况。例如,当服务器返回header("HTTP/1.0 418 I'm A Teapot: " . $filename);
时,客户端控制台就像:
PUT http://localhost:8182/audits/audits.php?filename=1.txt 418 (I'm A Teapot: 1.txt)
FINALLY: 1
Object {data: "", status: 418, config: Object, statusText: "I'm A Teapot: 1.txt"}
PUT http://localhost:8182/audits/audits.php?filename=2.txt 418 (I'm A Teapot: 2.txt)
FINALLY: 2
PUT http://localhost:8182/audits/audits.php?filename=3.txt 418 (I'm A Teapot: 3.txt)
FINALLY: 3
PUT http://localhost:8182/audits/audits.php?filename=4.txt 418 (I'm A Teapot: 4.txt)
FINALLY: 4
答案 0 :(得分:3)
$q.all
无弹性 正如其他人所说,$q.all
没有弹性。如果其中一个承诺被拒绝,$q.all
将被拒绝并出现第一个错误。
要创建弹性复合承诺,这是一个等待所有承诺完成通过或失败的承诺,请对每个承诺转换1}使用.catch
强烈的>被拒绝的成功承诺的承诺。
var resilientPromises = [];
angular.forEach(promises, function(p) {
var resilientP = p.catch( function(result) {
//return to convert rejection to success
return result;
});
resilientPromises.push(resilientP);
});
$q.all(resilientPromises).then( function (results) {
//process results
});
从这个答案中可以看出两件事:
$q.all
承诺不具弹性。它被第一个被拒绝的承诺拒绝。.then
方法的onRejected函数,从已拒绝的承诺中创建已履行的承诺。 有关详细信息,请参阅You're Missing the Point of Promises
答案 1 :(得分:2)
角度文档没有详细说明,但我相信Promise.all()
在这种情况下的行为与es2015 $q.all()
相同:
如果任何传入的承诺拒绝,则所有承诺立即拒绝拒绝的承诺的价值,放弃所有其他承诺,无论他们是否已经解决。
最有可能的是,至少有一个请求失败了。您的日志语句无法区分catch
是成功还是失败,但如果失败,您将看到的是第一个错误。
请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all了解报价来源。
修改强>
如果您想获得所有响应,即使某些响应失败,那么您应该在saveAudit
中添加function saveAudit(audit) {
var filename = audit.header.id + ".txt";
return $http({
method: 'PUT',
url: '/audits/audits.php?filename=' + encodeURIComponent(filename),
data: AuditSvc.getPlainAudit(audit.header.id)
}).catch(function(error) {
return { error:error};
})
.finally(function () {
$scope.sendAudits.progress += 1;
console.log("FINALLY: " + audit.header.id);
});
}
处理程序以将失败转换为成功的响应:
{{1}}
然后您需要检查每个响应以查看它是否包含错误或有效数据。