我有一套我希望同时运行的承诺。我正在使用$q.all
来实现这一目标。当一个承诺返回404响应时,任何其他承诺都无法完成。我希望能够在$ q.all函数上单独获得错误承诺。我该怎么做?
var idPais = 13, idUF = 20;
var promises = [
PaisAPI.list(),
UnidadeFederativaAPI.list(idPais),
MunicipioAPI.list(idUF)
];
$q.all(promises).then(
function(values) {
var paises = values[0].data;
var ufs = values[1].data;
var municipios = values[2].data;
console.log('paises ', paises.length);
console.log('ufs ', ufs.length);
console.log('municipios ', municipios.length);
$scope.paises = paises;
$scope.unidadesFederativas = ufs;
$scope.municipios = municipios;
},
function(error) {
if (error.status == 500) {
alert('Server error');
}
//when one of the promises get a 404 response any other one are unfulfilled
}
);
答案 0 :(得分:3)
我认为这是默认行为,符合Promises / A +规范,所有这些都建立在这些规范之上。
JS原生承诺的Documention声明:
Promise.all()方法返回一个Promise,它在iterable参数中的所有promise都已解析或者iterable参数不包含promise时解析。 它拒绝了第一个承诺拒绝的原因。
all()
的角度docs:
返回将使用值的数组/散列解析的单个promise,每个值对应于promises数组/散列中相同索引/键的promise。 如果任何承诺通过拒绝得到解决,则此结果承诺将被拒绝并具有相同的拒绝价值。
不同框架的所有实现都应该遵循并实际遵循这种方法。
作为一种解决方法,如果您的代码在ajax调用之后返回404错误,请尝试解决它而不是拒绝。我的意思是将此错误视为积极结果,并使用某些特殊值(如false
,{error: 404, message: 'Not Found'}
或0
来解决此问题 - 以便稍后显示客户端代码的差异。解决而不是拒绝应该让all()
等待,直到所有的承诺都完成。
答案 1 :(得分:2)
重新计算代码,以便在执行$scope
之前将值放在$q.all
上:
var idPais = 13, idUF = 20;
var promiseObj = {};
promiseObj.paises = PaisAPI.list()
.then(function (response) {
var paises = response.data;
console.log('paises ', paises.length);
$scope.paises = paises;
return paises;
}).catch(angular.identity);
promiseObj.ufs = UnidadeFederativaAPI.list(idPais)
.then(function (response) {
var ufs = response.data;
console.log('ufs ', ufs.length);
$scope.unidadesFederativas = ufs;
return ufs;
}).catch(angular.identity);
promiseObj.municipos = MunicipioAPI.list(idUF)
.then(function (response) {
var municipios = response.data;
console.log('municipios ', municipios.length);
$scope.municipios = municipios;
return municipios;
}).catch(angular.identity);
.catch(angular.identity);
将已拒绝的承诺转换为已履行的承诺。每个API调用都是并行执行的。
使用$q.all
等待所有承诺完成已完成或被拒绝:
$q.all(promiseObj).then(function (dataObj) {
console.log("All API calls complete");
if (dataObj.paises.status) {
console.log("paises failed with ",dataObj.paises.status);
};
if (dataObj.ufs.status) {
console.log("ufs failed with ",dataObj.ufs.status);
};
if (dataObj.municipos.status) {
console.log("municipos failed with ",dataObj.municipos.status);
};
});
将$q.all
与其他promise库区分开来的一件事是AngularJS $ q.all接受promises的对象哈希。
答案 2 :(得分:1)
您需要确保不应使$q.all()
失败的错误全部由个别承诺处理。您应该确保处理允许$q.all
正常完成的所有错误情况,但是如果还有其他错误仍然应该中止$q.all
那么应该通过使用$q.reject
。例如,在错误404上返回长度-1:
function handle404(error) {
if (error.status == 404) {
return { data: { length: -1 }};
}
return $q.reject(error)
}
var promises = [
PaisAPI.list().catch(handle404),
UnidadeFederativaAPI.list(idPais).catch(handle404),
MunicipioAPI.list(idUF).catch(handle404)
];
然后像以前一样代码的其余部分。或者只是在这些情况下返回一个空数组:
function handle404(error) {
if (error.status == 404) {
return { data: []};
}
return $q.reject(error)
}
但是这不能与没有错误的空数组区别开来。