我有一个函数可以对我的服务器进行Web服务调用并返回一个promises数组。
然而,其中一些呼叫可能有效,而其他呼叫可能无效。我的函数当前设置的方式,如果其中一个失败,它会警告整个事情都失败了。如果我正在拨5个电话,1可能会失败。我需要正确记录,我不知道该怎么做。
理想的响应/日志是:
现在整个事情将返回“句柄用户操作失败”,因为调用4失败。
功能:
var manageGroup = function (add, group, users){
var deffered = $q.defer();
var arrPromises = [];
var promiseIndex = arrPromises.length;
var usersLength = users.length;
var operation = add ? "AddUserToGroup" : "RemoveUserFromGroup";
var actionText = add ? "Added: " : "Removed: "
var actionText2 = add ? " to " : " from "
//Apply operation on selected groups
for (var i = 0; i < usersLength; i++){
arrPromises[i] = $().SPServices({
operation: operation,
groupName: group.name,
userLoginName: users[i].domain
});
}
$q.all(arrPromises).then(
function (){
//when promises are finsihed
for (var i = 0; i < usersLength; i++){
console.log(actionText + users[i].name + actionText2 + group.name);
};
deffered.resolve();
},
//function incase of AJAX failure
function (){
alert('The handle user operation failed.');
}
)
return deffered.promise;
}
我尝试单独处理promises而不是使用$ q.all但是现在我没有在日志中获得任何内容:
我把这部分拿出来了:
/*$q.all(arrPromises).then(
function (){
//when promises are finsihed
for (var i = 0; i < usersLength; i++){
console.log(actionText + users[i].name + actionText2 + group.name);
};
deferred.resolve();
},
//function incase of AJAX failure
function (){
alert('The handle user operation failed.');
}
) */
引入了这个:
for (var i = 0; i<promiseIndex; i++){
arrPromises[i].then(
function (){
console.log(actionText + user[i].name + actionText2 + group.name);
}
),
function (){
alert('Failed to add/remove'+ user[i].name + ' to ' + group.name)
}
}
$q.all(arrPromises).then(function (){
deferred.resolve();
}, function (){
deferred.reject();
})
答案 0 :(得分:5)
Q(ng。$ q所依据的)或bluebird有一种方法可以满足您的需求。
对于蓝鸟,你会这样:
var Promise = require('bluebird');
Promise.settle(arrPromises).then(function(promises) {
promises.forEach(function(p) {
if (promise.isRejected()) {
// it's a rejected promise.
}
else {
// it's a resolved promise.
}
});
});
对于Q,你会这样:
var Q = require('q');
Q.allSettled(arrPromises).then(function(promises) {
promises.forEach(function(p) {
if (p.state === 'fulfilled') {
// it's a resolved promise.
}
else {
// it's a rejected promise.
}
});
});
这两个库的好处在于它们符合Promises / A +规范。这意味着您可以取消。$ q,其中一个,您当前的代码仍然有用。
答案 1 :(得分:4)
似乎您遇到一个ajax调用失败导致all()
整体失败的问题。您可以捕获单个AJAX调用的失败,并使用您选择的值解析相应的promise。在这里,我只是使用一个空字符串。
<强> Live demo (click). 强>
请记住,这只是展示这一点的示例代码。
//store promises to use for all()
var promises = [];
//loop for ajax calls
for (var i=0; i<3; ++i) {
//new deferred for each call
var deferred = $q.defer();
//cache the promise
promises[i] = deferred.promise;
//use another function to avoid unwanted variable increment
makeCall(deferred, i);
}
$q.all(promises).then(function(allData) {
console.log(allData);
});
function makeCall(deferred, i) {
//make the ajax call
$http.get('file'+i+'.txt').then(function(resp) {
console.log('Call '+i+' returned.');
//resolve the promise with ajax data if successful
deferred.resolve(resp.data);
}, function() {
//resolve with something else on failure
deferred.resolve('');
});
}
答案 2 :(得分:1)
我试图单独处理承诺而不是使用$ q.all但现在我没有在日志中获得任何内容
当执行回调时,您i
变量的值错误<{3}}似乎已经下降了。相反,使用这个:
for (var i = 0; i<promiseIndex; i++) (function(i) {
arrPromises[i].then(function() {
console.log(actionText + user[i].name + actionText2 + group.name);
}, function( ){
alert('Failed to add/remove'+ user[i].name + ' to ' + group.name)
});
})(i);
你在then
调用中也有不匹配的括号,基本上没有传递错误处理程序。
现在,每个承诺都是单独处理的;然而他们的命令并没有坚持下去。为此,你需要使用某种all
,看看@ Florian的回答。
另请注意,没有理由明确使用deffered
。只是return $q.all(arrPromises)
!手动解决延迟并返回其承诺是繁琐且容易出错的 - 在您的原始代码中,您只是忘记在发生错误时拒绝它。当你已经有了承诺并且可以在它们上面使用组合器时,请不要使用它。