当某些承诺失败时如何继续 $q.all()
how to continue with $q.all() when some promises fail
我有一组承诺,每个承诺调用 http.get()
。
var items = ["URL1", "URL2", "URL3"];
var promises = [];
//on each URL in items array, I want to create a promise and call http.get
items.forEach(function(el){
return promises.push($http.get(el));
});
var all = $q.all(promises);
all.then(function success(data){
console.log(data);
}).catch(function(reason){
console.log("reason is", reason);
});
我的情况如何
URL2.get
没有解决,直接触发了$q.all
中的catch()
。由于这次失败,all.then()
永远不会被调用。
我想要的
即使其中一个承诺被拒绝,我也希望所有承诺继续。
我找到了一个类似的 post,但解决方案建议使用另一个 angular 包,称为 Kris Kowal 的 Q。所以我想知道如何在不使用外部包的情况下实现它?
一个简单的 hack 可能是添加一个 catch 块来承诺 return null,并从你的 promise.all
结果中过滤出 null 结果,比如:
let items = ["URL1", "URL2", "URL3"]
, promises = items.map(url => $http.get(url).catch(e => null))
, all = $q.all(promises).then(data => data.filter(d => !!d))
all.then(data => {
// do something with data
}).catch(e => {
// some error action
})
ES5 中的相同内容:
var items = ["URL1", "URL2", "URL3"]
, promises = items.map(function(url){
return $http.get(url).catch(function(e){return null})
})
, all = $q.all(promises).then(function(data){
return data.filter(function(d){return !!d}) // filter out empty, null results
})
all.then(function(data){
// do something with data
}).catch(function(e){
// some error action
})
这是 .settle()
的 ES6 兼容版本,它允许完成所有承诺,然后您可以查询每个结果以查看它是成功还是失败:
// ES6 version of settle
Promise.settle = function(promises) {
function PromiseInspection(fulfilled, val) {
return {
isFulfilled: function() {
return fulfilled;
}, isRejected: function() {
return !fulfilled;
}, isPending: function() {
// PromiseInspection objects created here are never pending
return false;
}, value: function() {
if (!fulfilled) {
throw new Error("Can't call .value() on a promise that is not fulfilled");
}
return val;
}, reason: function() {
if (fulfilled) {
throw new Error("Can't call .reason() on a promise that is fulfilled");
}
return val;
}
};
}
return Promise.all(promises.map(function(p) {
// make sure any values or foreign promises are wrapped in a promise
return Promise.resolve(p).then(function(val) {
return new PromiseInspection(true, val);
}, function(err) {
return new PromiseInspection(false, err);
});
}));
}
这可以像这样适用于 Q 库:
// Q version of settle
$q.settle = function(promises) {
function PromiseInspection(fulfilled, val) {
return {
isFulfilled: function() {
return fulfilled;
}, isRejected: function() {
return !fulfilled;
}, isPending: function() {
// PromiseInspection objects created here are never pending
return false;
}, value: function() {
if (!fulfilled) {
throw new Error("Can't call .value() on a promise that is not fulfilled");
}
return val;
}, reason: function() {
if (fulfilled) {
throw new Error("Can't call .reason() on a promise that is fulfilled");
}
return val;
}
};
}
return $q.all(promises.map(function(p) {
// make sure any values or foreign promises are wrapped in a promise
return $q(p).then(function(val) {
return new PromiseInspection(true, val);
}, function(err) {
return new PromiseInspection(false, err);
});
}));
}
使用您的特定代码:
var items = ["URL1", "URL2", "URL3"];
$q.settle(items.map(function(url) {
return $http.get(url);
})).then(function(data){
data.forEach(function(item) {
if (item.isFulfilled()) {
console.log("success: ", item.value());
} else {
console.log("fail: ", item.reason());
}
});
});
注意:.settle()
returns 一个总是解决的承诺,从不拒绝。这是因为无论您传递给它的承诺有多少被拒绝,它仍然会解决,但是 returns 关于您传递给它的承诺的信息会解决或拒绝。
我将 $resource 包装在 $q 中,只有解析状态
var promises = [
$q(function (resolve) {
Me.get({params: 12}).$promise.then(function (data) {
resolve(data);
}, function (err) {
resolve(err);
});
}),
$q(function (resolve) {
Me.get({params: 123}).$promise.then(function (data) {
resolve(data);
}, function (err) {
resolve(err);
});
}),
$q(function (resolve) {
Me.get({params: 124}).$promise.then(function (data) {
resolve(data);
}, function (err) {
resolve(err);
});
})];
然后使用 $q.all 来承诺
我有一组承诺,每个承诺调用 http.get()
。
var items = ["URL1", "URL2", "URL3"];
var promises = [];
//on each URL in items array, I want to create a promise and call http.get
items.forEach(function(el){
return promises.push($http.get(el));
});
var all = $q.all(promises);
all.then(function success(data){
console.log(data);
}).catch(function(reason){
console.log("reason is", reason);
});
我的情况如何
URL2.get
没有解决,直接触发了$q.all
中的catch()
。由于这次失败,all.then()
永远不会被调用。
我想要的
即使其中一个承诺被拒绝,我也希望所有承诺继续。
我找到了一个类似的 post,但解决方案建议使用另一个 angular 包,称为 Kris Kowal 的 Q。所以我想知道如何在不使用外部包的情况下实现它?
一个简单的 hack 可能是添加一个 catch 块来承诺 return null,并从你的 promise.all
结果中过滤出 null 结果,比如:
let items = ["URL1", "URL2", "URL3"]
, promises = items.map(url => $http.get(url).catch(e => null))
, all = $q.all(promises).then(data => data.filter(d => !!d))
all.then(data => {
// do something with data
}).catch(e => {
// some error action
})
ES5 中的相同内容:
var items = ["URL1", "URL2", "URL3"]
, promises = items.map(function(url){
return $http.get(url).catch(function(e){return null})
})
, all = $q.all(promises).then(function(data){
return data.filter(function(d){return !!d}) // filter out empty, null results
})
all.then(function(data){
// do something with data
}).catch(function(e){
// some error action
})
这是 .settle()
的 ES6 兼容版本,它允许完成所有承诺,然后您可以查询每个结果以查看它是成功还是失败:
// ES6 version of settle
Promise.settle = function(promises) {
function PromiseInspection(fulfilled, val) {
return {
isFulfilled: function() {
return fulfilled;
}, isRejected: function() {
return !fulfilled;
}, isPending: function() {
// PromiseInspection objects created here are never pending
return false;
}, value: function() {
if (!fulfilled) {
throw new Error("Can't call .value() on a promise that is not fulfilled");
}
return val;
}, reason: function() {
if (fulfilled) {
throw new Error("Can't call .reason() on a promise that is fulfilled");
}
return val;
}
};
}
return Promise.all(promises.map(function(p) {
// make sure any values or foreign promises are wrapped in a promise
return Promise.resolve(p).then(function(val) {
return new PromiseInspection(true, val);
}, function(err) {
return new PromiseInspection(false, err);
});
}));
}
这可以像这样适用于 Q 库:
// Q version of settle
$q.settle = function(promises) {
function PromiseInspection(fulfilled, val) {
return {
isFulfilled: function() {
return fulfilled;
}, isRejected: function() {
return !fulfilled;
}, isPending: function() {
// PromiseInspection objects created here are never pending
return false;
}, value: function() {
if (!fulfilled) {
throw new Error("Can't call .value() on a promise that is not fulfilled");
}
return val;
}, reason: function() {
if (fulfilled) {
throw new Error("Can't call .reason() on a promise that is fulfilled");
}
return val;
}
};
}
return $q.all(promises.map(function(p) {
// make sure any values or foreign promises are wrapped in a promise
return $q(p).then(function(val) {
return new PromiseInspection(true, val);
}, function(err) {
return new PromiseInspection(false, err);
});
}));
}
使用您的特定代码:
var items = ["URL1", "URL2", "URL3"];
$q.settle(items.map(function(url) {
return $http.get(url);
})).then(function(data){
data.forEach(function(item) {
if (item.isFulfilled()) {
console.log("success: ", item.value());
} else {
console.log("fail: ", item.reason());
}
});
});
注意:.settle()
returns 一个总是解决的承诺,从不拒绝。这是因为无论您传递给它的承诺有多少被拒绝,它仍然会解决,但是 returns 关于您传递给它的承诺的信息会解决或拒绝。
我将 $resource 包装在 $q 中,只有解析状态
var promises = [
$q(function (resolve) {
Me.get({params: 12}).$promise.then(function (data) {
resolve(data);
}, function (err) {
resolve(err);
});
}),
$q(function (resolve) {
Me.get({params: 123}).$promise.then(function (data) {
resolve(data);
}, function (err) {
resolve(err);
});
}),
$q(function (resolve) {
Me.get({params: 124}).$promise.then(function (data) {
resolve(data);
}, function (err) {
resolve(err);
});
})];
然后使用 $q.all 来承诺