Quelqu'un a présenté un cas intéressant aujourd'hui avec Bluebird, quelle est la meilleure façon de gérer plusieurs promesses où nous ne sommes pas intéressés à arrêter un accomplissement ou un rejet donné, mais plutôt à inspecter le résultat final. Un exemple:
var p1 = new Promise(function(f,r){
setTimeout(function(){
console.log("p1");
f("yay");
}, 100);
});
var p2 = new Promise(function(f,r){
setTimeout(function(){
console.log("p2");
r(new Error("boo"));
}, 200);
})
var p3 = new Promise(function(f,r){
setTimeout(function(){
console.log("p3");
r(new Error("yay"));
}, 300);
});
var p4 = new Promise(function(f,r){
setTimeout(function(){
console.log("p4");
f("yay");
}, 400);
});
//Promise.all([p1,p2, p3, p4]).then(function(p){
// console.log("Results:",p);
//}).error(function(e){
// console.log("Error:",e);
//});
Promise.map([p1,p2, p3, p4],function(p){
console.log("results:",p);
}, {concurrency:10}).error(function(e){
console.log("Error:",e);
});
Ici, si nous exécutons une carte ou toutes les promesses rejetées, les gestionnaires ne rapporteront pas les résultats.
Par exemple, les résultats de l'exécution de Promise.map tels qu'implémentés ci-dessus sont:
debugger listening on port 65222
p1
results: yay
p2
Error: [Error: boo]
p3
p4
Process finished with exit code 0
Ici, le code de chaque promesse s'exécute, mais seulement 1 résultat et 1 erreur sont signalés. L'erreur entraîne l'arrêt du processus.
Si nous décommentons tous, nous obtenons un comportement similaire. Cette fois, seule l'erreur est signalée. Aucun succès ne se concrétise alors (naturellement).
debugger listening on port 65313
p1
p2
Error: [Error: boo]
p3
p4
Process finished with exit code 0
Compte tenu de ce comportement, quelle serait la meilleure façon de procéder pour mettre en œuvre un scénario dans lequel toutes les promesses sont exécutées et les résultats des promesses remplies sont signalés avec tous les refus?
Quelque chose comme:
Promise.aggregate([p1,p2,p3,p4]).then(function(fulfilled, rejected){
console.log(fulfilled); //all success
console.log(rejected); //any and all rejections/exceptions
});
Vous utiliseriez .reflect
:
Promise.all([p1,p2,p3,p4].map(x => x.reflect()).then(results => {
results.forEach(result => {
if(result.isFulfilled()){
// access result.value()
} else {
// access result.reason()
}
});
});
Auparavant, cela était géré avec une fonction settle
qui faisait cela pour un tableau traditionnellement - elle était généralisée par .reflect
car il sépare l'agrégation de la notion d'inspection de promesse et vous permet de faire ce que .settle
l'a fait mais à d'autres actions comme .any
ou .some
ainsi que.