Gestion des erreurs dans Promise.all

267

J'ai un éventail de promesses avec lesquelles je résous Promise.all(arrayOfPromises);

Je continue la chaîne de promesses. Ressemble à quelque chose comme ça

existingPromiseChain = existingPromiseChain.then(function() {
  var arrayOfPromises = state.routes.map(function(route){
    return route.handler.promiseHandler();
  });
  return Promise.all(arrayOfPromises)
});

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
  // do stuff with my array of resolved promises, eventually ending with a res.send();
});

Je veux ajouter une instruction catch pour gérer une promesse individuelle en cas d'erreur, mais lorsque j'essaie, Promise.allrenvoie la première erreur trouvée (ignore le reste), puis je ne peux pas obtenir les données du reste des promesses dans le tableau (qui n'a pas fait d'erreur).

J'ai essayé de faire quelque chose comme ..

existingPromiseChain = existingPromiseChain.then(function() {
      var arrayOfPromises = state.routes.map(function(route){
        return route.handler.promiseHandler()
          .then(function(data) {
             return data;
          })
          .catch(function(err) {
             return err
          });
      });
      return Promise.all(arrayOfPromises)
    });

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
      // do stuff with my array of resolved promises, eventually ending with a res.send();
});

Mais cela ne résout pas.

Merci!

-

Éditer:

Ce que les réponses ci-dessous ont dit était complètement vrai, le code cassait pour d'autres raisons. Si quelqu'un est intéressé, c'est la solution avec laquelle je me suis retrouvé ...

Chaîne de serveurs Node Express

serverSidePromiseChain
    .then(function(AppRouter) {
        var arrayOfPromises = state.routes.map(function(route) {
            return route.async();
        });
        Promise.all(arrayOfPromises)
            .catch(function(err) {
                // log that I have an error, return the entire array;
                console.log('A promise failed to resolve', err);
                return arrayOfPromises;
            })
            .then(function(arrayOfPromises) {
                // full array of resolved promises;
            })
    };

Appel API (appel route.async)

return async()
    .then(function(result) {
        // dispatch a success
        return result;
    })
    .catch(function(err) {
        // dispatch a failure and throw error
        throw err;
    });

Mettre le .catchfor Promise.allavant le .thensemble avoir permis de détecter les erreurs des promesses originales, mais de renvoyer ensuite l'ensemble du tableau au suivant.then

Merci!

Jon
la source
2
Votre tentative semble fonctionner: peut-être qu'il y a un autre problème quelque part plus tard?
Ry-
.then(function(data) { return data; })peut être complètement omis
Bergi
La seule raison pour laquelle ce qui précède ne devrait pas être résolu est que si vous ne nous montrez pas tout le code dans les gestionnaires thenou catchet qu'une erreur est générée à l'intérieur. Soit dit en passant, est ce nœud?
1
Vous n'avez pas de prise finale dans votre "chaîne existante", il peut donc y avoir des erreurs que vous ne voyez pas qui pourraient expliquer pourquoi il "ne résout pas". Essayez d'ajouter cela et voyez quelle erreur vous obtenez.
foc
voici la réponse: stackoverflow.com/questions/31424561/…
Humoyun Ahmad

Réponses:

191

Promise.allc'est tout ou rien. Il résout une fois que toutes les promesses du tableau sont résolues, ou rejetées dès que l' une d'elles rejette. En d'autres termes, il résout soit avec un tableau de toutes les valeurs résolues, soit il rejette avec une seule erreur.

Certaines bibliothèques ont quelque chose appelé Promise.when, qui, à ma connaissance, attendrait toutes les promesses du tableau à résoudre ou à rejeter, mais je ne le connais pas et ce n'est pas dans ES6.

Votre code

Je suis d'accord avec les autres ici que votre solution devrait fonctionner. Il doit être résolu avec un tableau qui peut contenir un mélange de valeurs réussies et d'objets erreurs. Il est inhabituel de passer des objets d'erreur dans le chemin de réussite, mais en supposant que votre code les attend, je ne vois aucun problème avec cela.

La seule raison pour laquelle je peux penser pourquoi cela "ne résoudrait pas" est qu'il échoue dans le code que vous ne nous montrez pas et que vous ne voyez aucun message d'erreur à ce sujet parce que cette chaîne de promesses n'est pas terminée par un final attraper (autant que ce que vous nous montrez de toute façon).

J'ai pris la liberté de factoriser la "chaîne existante" de votre exemple et de terminer la chaîne avec un crochet. Cela ne vous convient peut-être pas, mais pour les personnes qui lisent ceci, il est important de toujours renvoyer ou terminer les chaînes, sinon les erreurs potentielles, même les erreurs de codage, seront masquées (ce qui, je suppose, s'est produit ici):

Promise.all(state.routes.map(function(route) {
  return route.handler.promiseHandler().catch(function(err) {
    return err;
  });
}))
.then(function(arrayOfValuesOrErrors) {
  // handling of my array containing values and/or errors. 
})
.catch(function(err) {
  console.log(err.message); // some coding error in handling happened
});
foc
la source
4
Vous (et les commentaires ci-dessus) aviez raison. Mon itinéraire.handler.promiseHandler avait besoin de .catch () et de renvoyer l'erreur. J'ai également dû ajouter le .catch () final à la fin de la chaîne. Merci d'avoir relayé l'importance d'avoir des gestionnaires de réussite / erreur à chaque étape de la chaîne :).
Jon
2
J'ai également découvert que si je jette l'erreur dans mon .catch () pour route.handler.promiseHandler, il ira automatiquement à la capture finale. Si je renvoie l'erreur à la place, il fera ce que je veux et traitera l'ensemble du tableau.
Jon
2
Il existe maintenant une méthode standard Promise.allSettled()avec un support décent. Voir référence .
Andréa Maugars
Oui, Promise.alléchoue, lorsque le premier thread échoue. Mais malheureusement, tous les autres threads continuent de fonctionner jusqu'à ce qu'ils se terminent. Rien n'est annulé, pire encore: il n'y a aucun moyen d'annuler un thread Promise. Donc, quoi que les threads fassent (et manipulent), ils continuent, ils changent les états et les variables, ils utilisent le CPU, mais à la fin ils ne retournent pas leur résultat. Vous devez en être conscient pour ne pas créer de chaos, par exemple lorsque vous répétez / réessayez l'appel.
Marc Wäckerlin
144

NOUVELLE RÉPONSE

const results = await Promise.all(promises.map(p => p.catch(e => e)));
const validResults = results.filter(result => !(result instanceof Error));

API FUTURE Promise

Solominh
la source
11
Mais ene doit pas nécessairement être un Error. Il peut s'agir d'une chaîne, par exemple, si quelqu'un la renvoie comme Promise.reject('Service not available').
Klesun
@ArturKlesun comment pourrions-nous alors classer laquelle des promesses a entraîné une erreur et laquelle ne l'a pas été?
Shubham Jain
5
@ shubham-jain avec .then()et .catch(). Promise.resolve()transmettrait de la valeur à la première, tandis Promise.reject()qu'elle la transmettrait à la seconde. Vous pouvez les envelopper dans l' objet , par exemple: p.then(v => ({success: true, value: v})).catch(e => ({success: false, error: e})).
Klesun
2
Pourquoi filtreriez-vous les résultats? Cela n'a aucun sens si vous faites quoi que ce soit avec les résultats - vous avez besoin de l'ordre pour savoir quelle valeur retournée est de quelle promesse!
Ryan Taylor
21

Pour continuer la Promise.allboucle (même lorsqu'une promesse refuse), j'ai écrit une fonction utilitaire qui est appelée executeAllPromises. Cette fonction utilitaire renvoie un objet avec resultset errors.

L'idée est que toutes les promesses auxquelles vous passez executeAllPromisesseront enveloppées dans une nouvelle promesse qui sera toujours résolue. La nouvelle promesse se résout avec un tableau qui a 2 spots. Le premier emplacement contient la valeur de résolution (le cas échéant) et le second emplacement conserve l'erreur (si la promesse encapsulée rejette).

Comme étape finale, le executeAllPromisesaccumule toutes les valeurs des promesses encapsulées et retourne l'objet final avec un tableau pour resultset un tableau pour errors.

Voici le code:

function executeAllPromises(promises) {
  // Wrap all Promises in a Promise that will always "resolve"
  var resolvingPromises = promises.map(function(promise) {
    return new Promise(function(resolve) {
      var payload = new Array(2);
      promise.then(function(result) {
          payload[0] = result;
        })
        .catch(function(error) {
          payload[1] = error;
        })
        .then(function() {
          /* 
           * The wrapped Promise returns an array:
           * The first position in the array holds the result (if any)
           * The second position in the array holds the error (if any)
           */
          resolve(payload);
        });
    });
  });

  var errors = [];
  var results = [];

  // Execute all wrapped Promises
  return Promise.all(resolvingPromises)
    .then(function(items) {
      items.forEach(function(payload) {
        if (payload[1]) {
          errors.push(payload[1]);
        } else {
          results.push(payload[0]);
        }
      });

      return {
        errors: errors,
        results: results
      };
    });
}

var myPromises = [
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.reject(new Error('3')),
  Promise.resolve(4),
  Promise.reject(new Error('5'))
];

executeAllPromises(myPromises).then(function(items) {
  // Result
  var errors = items.errors.map(function(error) {
    return error.message
  }).join(',');
  var results = items.results.join(',');
  
  console.log(`Executed all ${myPromises.length} Promises:`);
  console.log(`— ${items.results.length} Promises were successful: ${results}`);
  console.log(`— ${items.errors.length} Promises failed: ${errors}`);
});

Benny Neugebauer
la source
2
Cela peut être fait plus simplement. Voir stackoverflow.com/a/36115549/918910
jib
18

ES2020 introduit une nouvelle méthode pour le type de promesse: Promise.allSettled()
Promise.allSettled vous donne un signal lorsque toutes les promesses d'entrée sont réglées, ce qui signifie qu'elles sont remplies ou rejetées. Ceci est utile dans les cas où vous ne vous souciez pas de l'état de la promesse, vous voulez simplement savoir quand le travail est terminé, qu'il ait réussi ou non.

const promises = [
  fetch('/api-call-1'),
  fetch('/api-call-2'),
  fetch('/api-call-3'),
];
// Imagine some of these requests fail, and some succeed.

const result = await Promise.allSettled(promises);
console.log(result.map(x=>s.status));
// ['fulfilled', 'fulfilled', 'rejected']

En savoir plus dans le blog v8 https://v8.dev/features/promise-combinators

MosheZada
la source
13

Comme l'a dit @jib,

Promise.all c'est tout ou rien.

Cependant, vous pouvez contrôler certaines promesses qui sont "autorisées" à échouer et nous aimerions continuer .then.

Par exemple.

  Promise.all([
    doMustAsyncTask1,
    doMustAsyncTask2,
    doOptionalAsyncTask
    .catch(err => {
      if( /* err non-critical */) {
        return
      }
      // if critical then fail
      throw err
    })
  ])
  .then(([ mustRes1, mustRes2, optionalRes ]) => {
    // proceed to work with results
  })
Herman
la source
6

si vous arrivez à utiliser la bibliothèque q https://github.com/kriskowal/q, elle dispose de la méthode q.allSettled () qui peut résoudre ce problème, vous pouvez gérer chaque promesse en fonction de son état soit complet, soit rejeté, donc

existingPromiseChain = existingPromiseChain.then(function() {
var arrayOfPromises = state.routes.map(function(route){
  return route.handler.promiseHandler();
});
return q.allSettled(arrayOfPromises)
});

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
//so here you have all your promises the fulfilled and the rejected ones
// you can check the state of each promise
arrayResolved.forEach(function(item){
   if(item.state === 'fulfilled'){ // 'rejected' for rejected promises
     //do somthing
   } else {
     // do something else
   }
})
// do stuff with my array of resolved promises, eventually ending with a res.send();
});
Mohamed Mahmoud
la source
Puisque vous proposez l'utilisation d'une bibliothèque ( q), il serait plus utile de fournir un exemple d'utilisation lié à la question. En l'état, votre réponse n'explique pas comment cette bibliothèque peut aider à résoudre le problème.
ishmaelMakitla
a ajouté un exemple comme suggéré
Mohamed Mahmoud
1
Vers 2018, il faut toujours voir ce que Sindre a à disposition :-). github.com/sindresorhus/p-settle . Avec les modules à usage unique de Sindre, vous n'avez pas besoin d'importer une énorme bibliothèque comme q pour un seul bit.
DKebler
6

Utilisation d'Async wait -

ici, une fonction asynchrone func1 renvoie une valeur résolue, et func2 renvoie une erreur et renvoie une valeur nulle dans cette situation, nous pouvons la gérer comme nous le voulons et retourner en conséquence.

const callingFunction  = async () => {
    const manyPromises = await Promise.all([func1(), func2()]);
    console.log(manyPromises);
}


const func1 = async () => {
    return 'func1'
}

const func2 = async () => {
    try {
        let x;
        if (!x) throw "x value not present"
    } catch(err) {
       return null
    }
}

callingFunction();

La sortie est - ['func1', null]

Nayan Patel
la source
4

Pour ceux qui utilisent ES8 qui trébuchent ici, vous pouvez faire quelque chose comme ceci, en utilisant des fonctions asynchrones :

var arrayOfPromises = state.routes.map(async function(route){
  try {
    return await route.handler.promiseHandler();
  } catch(e) {
    // Do something to handle the error.
    // Errored promises will return whatever you return here (undefined if you don't return anything).
  }
});

var resolvedPromises = await Promise.all(arrayOfPromises);
Tyler Yasaka
la source
3

Nous pouvons gérer le rejet au niveau des promesses individuelles, donc lorsque nous obtenons les résultats dans notre tableau de résultats, l'index du tableau qui a été rejeté sera undefined . Nous pouvons gérer cette situation au besoin et utiliser les résultats restants.

Ici, j'ai rejeté la première promesse, elle est donc indéfinie, mais nous pouvons utiliser le résultat de la deuxième promesse, qui est à l'index 1.

const manyPromises = Promise.all([func1(), func2()]).then(result => {
    console.log(result[0]);  // undefined
    console.log(result[1]);  // func2
});

function func1() {
    return new Promise( (res, rej) => rej('func1')).catch(err => {
        console.log('error handled', err);
    });
}

function func2() {
    return new Promise( (res, rej) => setTimeout(() => res('func2'), 500) );
}

Nayan Patel
la source
Comment pouvez-vous faire une chose similaire si nous utilisons l'attente asynchrone?
Rudresh Ajgaonkar
J'ai répondu à votre question, veuillez trouver le lien pour la réponse. stackoverflow.com/a/55216763/4079716
Nayan Patel
2

Avez-vous réfléchi Promise.prototype.finally()?

Il semble être conçu pour faire exactement ce que vous voulez - exécuter une fonction une fois que toutes les promesses ont été réglées (résolues / rejetées), indépendamment de certaines des promesses rejetées.

De la documentation MDN :

La finally()méthode peut être utile si vous souhaitez effectuer un traitement ou un nettoyage une fois la promesse réglée, quel que soit son résultat.

La finally()méthode est très similaire à l'appel, .then(onFinally, onFinally)mais il existe quelques différences:

Lors de la création d'une fonction en ligne, vous pouvez la transmettre une fois, au lieu d'être obligé de la déclarer deux fois ou de créer une variable pour elle.

Un rappel final ne recevra aucun argument, car il n'existe aucun moyen fiable de déterminer si la promesse a été tenue ou rejetée. Ce cas d'utilisation est précisément lorsque vous ne vous souciez pas de la raison du rejet ou de la valeur de réalisation, et il n'est donc pas nécessaire de le fournir.

Contrairement à Promise.resolve(2).then(() => {}, () => {})(qui sera résolu avec undefined), Promise.resolve(2).finally(() => {})sera résolu avec 2. De même, contrairement à Promise.reject(3).then(() => {}, () => {})(qui sera rempli avec undefined), Promise.reject(3).finally(() => {})sera rejeté avec 3.

== Repli ==

Si votre version de JavaScript ne prend pas en charge, Promise.prototype.finally()vous pouvez utiliser cette solution de contournement de Jake Archibald :Promise.all(promises.map(p => p.catch(() => undefined)));

Tom Auger
la source
1
Oui, jusqu'à ce qu'il Promises.allSettled()soit réellement implémenté (c'est documenté par MDN ici ), alors Promises.all.finally()il semblerait que la même chose soit accomplie. Je suis sur le point d'essayer ...
jamess
@jamess Pourquoi ne faites-vous pas ce commentaire comme une bonne réponse? Aucune des réponses ne fait référence à ES6 allSettled().
pravin du
@pravin - D'après ce que je peux dire, allSettled()n'est pas implémenté nulle part (encore), donc je ne veux pas prendre de l'avance sur la réalité. J'ai eu du succès avec Promises.all(myPromiseArray).finally(), et cela correspond à cette réponse. Une fois allSettled()qu'il existe réellement, je pourrais le tester et découvrir comment cela fonctionne réellement. D'ici là, qui sait ce que les navigateurs implémenteront réellement? Sauf si vous avez des informations récentes à l'effet contraire ...
jamess
@jamess Il est vrai que sa version en cours de développement .. mais les derniers FF et chrome semblent le supporter pleinement .. Je ne suis pas sûr de sa stabilité. Mozilla Docs Quoi qu'il en soit, j'essayais de dire qu'il aurait été beaucoup plus facile à trouver si c'était une réponse plutôt qu'un commentaire .. c'est votre appel
quand
@pravin - Au moment où j'ai posté mon commentaire, il n'était implémenté nulle part. Je viens de tester dans Firefox et Chrome: Promise.allSettledn'est pas implémenté dans Firefox, mais il semble exister dans Chrome. Ce n'est pas parce que les documents disent qu'il est implémenté qu'il est vraiment implémenté. Je ne vais pas l'utiliser de sitôt.
jamess
0

Alternativement, si vous avez un cas où vous ne vous souciez pas particulièrement des valeurs des promesses résolues quand il y a un échec mais que vous voulez toujours qu'elles se soient déroulées, vous pouvez faire quelque chose comme ça qui résoudra les promesses normalement lorsque ils réussissent tous et rejettent avec les promesses manquées quand l'un d'eux échoue:

function promiseNoReallyAll (promises) {
  return new Promise(
    async (resolve, reject) => {
      const failedPromises = []

      const successfulPromises = await Promise.all(
        promises.map(
          promise => promise.catch(error => {
            failedPromises.push(error)
          })
        )
      )

      if (failedPromises.length) {
        reject(failedPromises)
      } else {
        resolve(successfulPromises)
      }
    }
  )
}
Eric
la source
0

Vous pouvez toujours envelopper vos fonctions de retour de promesse d'une manière qui attrape l'échec et renvoie à la place une valeur convenue (par exemple error.message), de sorte que l'exception ne sera pas transférée jusqu'à la fonction Promise.all et la désactiver.

async function resetCache(ip) {

    try {

        const response = await axios.get(`http://${ip}/resetcache`);
        return response;

    }catch (e) {

        return {status: 'failure', reason: 'e.message'};
    }

}
Tamir Nakar
la source
0

J'ai trouvé un moyen (solution de contournement) de le faire sans le synchroniser.

Donc, comme cela a été mentionné précédemment Promise.all tout est nul.

alors ... Utilisez une promesse englobante pour attraper et forcer la résolution.


      let safePromises = originalPrmises.map((imageObject) => {
            return new Promise((resolve) => {
              // Do something error friendly
              promise.then(_res => resolve(res)).catch(_err => resolve(err))
            })
        })
    })

    // safe
    return Promise.all(safePromises)
Juan Sebastian Contreras Aceve
la source
0

Vous devez savoir comment identifier une erreur dans vos résultats. Si vous n'avez pas d'erreur standard attendue, je vous suggère d'exécuter une transformation sur chaque erreur dans le bloc catch qui la rend identifiable dans vos résultats.

try {
  let resArray = await Promise.all(
    state.routes.map(route => route.handler.promiseHandler().catch(e => e))
  );

  // in catch(e => e) you can transform your error to a type or object
  // that makes it easier for you to identify whats an error in resArray
  // e.g. if you expect your err objects to have e.type, you can filter
  // all errors in the array eg
  // let errResponse = resArray.filter(d => d && d.type === '<expected type>')
  // let notNullResponse = resArray.filter(d => d)

  } catch (err) {
    // code related errors
  }
Anthony Awuley
la source
0

Ce n'est pas le meilleur moyen de consigner les erreurs, mais vous pouvez toujours tout définir sur un tableau pour promiseAll et stocker les résultats résultants dans de nouvelles variables.

Si vous utilisez graphQL, vous devez malgré tout post-traiter la réponse et si elle ne trouve pas la référence correcte, l'application se bloquera, ce qui réduira l'emplacement du problème.

const results = await Promise.all([
  this.props.client.query({
    query: GET_SPECIAL_DATES,
  }),
  this.props.client.query({
    query: GET_SPECIAL_DATE_TYPES,
  }),
  this.props.client.query({
    query: GET_ORDER_DATES,
  }),
]).catch(e=>console.log(e,"error"));
const specialDates = results[0].data.specialDates;
const specialDateTypes = results[1].data.specialDateTypes;
const orderDates = results[2].data.orders;
Vincent Tang
la source
-1

Voilà comment Promise.allest conçu pour fonctionner. Si une seule promesse est faite reject(), la méthode entière échoue immédiatement.

Il existe des cas d'utilisation où l'on peut souhaiter que les Promise.allpromesses échouent. Pour ce faire, n'utilisez simplement aucune reject()déclaration dans votre promesse. Cependant, pour vous assurer que votre application / script ne se fige pas au cas où une seule promesse sous-jacente n'obtiendrait jamais de réponse, vous devez y mettre un délai d'attente.

function getThing(uid,branch){
    return new Promise(function (resolve, reject) {
        xhr.get().then(function(res) {
            if (res) {
                resolve(res);
            } 
            else {
                resolve(null);
            }
            setTimeout(function(){reject('timeout')},10000)
        }).catch(function(error) {
            resolve(null);
        });
    });
}
Ronnie Royston
la source
voici la réponse: stackoverflow.com/questions/31424561/…
Humoyun Ahmad
Ne pas utiliser reject()dans votre promesse est bien, mais que faire si vous avez besoin d'utiliser les promesses d'une autre bibliothèque?
Dan Dascalescu
-8

J'ai écrit une bibliothèque npm pour faire face à ce problème plus beau. https://github.com/wenshin/promiseallend

Installer

npm i --save promiseallend

2017-02-25 nouvelle API, ce n'est pas rompre les principes de la promesse

const promiseAllEnd = require('promiseallend');

const promises = [Promise.resolve(1), Promise.reject('error'), Promise.resolve(2)];
const promisesObj = {k1: Promise.resolve(1), k2: Promise.reject('error'), k3: Promise.resolve(2)};

// input promises with array
promiseAllEnd(promises, {
    unhandledRejection(error, index) {
        // error is the original error which is 'error'.
        // index is the index of array, it's a number.
        console.log(error, index);
    }
})
    // will call, data is `[1, undefined, 2]`
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

// input promises with object
promiseAllEnd(promisesObj, {
    unhandledRejection(error, prop) {
        // error is the original error.
        // key is the property of object.
        console.log(error, prop);
    }
})
    // will call, data is `{k1: 1, k3: 2}`
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

// the same to `Promise.all`
promiseAllEnd(promises, {requireConfig: true})
    // will call, `error.detail` is 'error', `error.key` is number 1.
    .catch(error => console.log(error.detail))

// requireConfig is Array
promiseAllEnd(promises, {requireConfig: [false, true, false]})
    // won't call
    .then(data => console.log(data))
    // will call, `error.detail` is 'error', `error.key` is number 1.
    .catch(error => console.log(error.detail))

// requireConfig is Array
promiseAllEnd(promises, {requireConfig: [true, false, false]})
    // will call, data is `[1, undefined, 2]`.
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

————————————————————————————————

Vieille mauvaise api, ne l'utilisez pas!

let promiseAllEnd = require('promiseallend');

// input promises with array
promiseAllEnd([Promise.resolve(1), Promise.reject('error'), Promise.resolve(2)])
    .then(data => console.log(data)) // [1, undefined, 2]
    .catch(error => console.log(error.errorsByKey)) // {1: 'error'}

// input promises with object
promiseAllEnd({k1: Promise.resolve(1), k2: Promise.reject('error'), k3: Promise.resolve(2)})
    .then(data => console.log(data)) // {k1: 1, k3: 2}
    .catch(error => console.log(error.errorsByKey)) // {k2: 'error'}
wenshin
la source
Comment ça marche? Veuillez montrer et expliquer votre implémentation de la fonction.
Bergi
J'ai écrit une nouvelle logique concurrente comme Promise.all. Mais il collectera toutes les données et les erreurs de chaque promesse. il prend également en charge la saisie d'objets, ce n'est pas un point. après avoir collecté toutes les données et les erreurs, je remplace la promise.thenméthode pour traiter les rappels enregistrés, notamment rejetés et satisfaits. Pour plus de détails, vous pouvez voir le code
wenshin
Euh, ce code appellera les deux onFulfilledet les onRejectedgestionnaires qui sont passés à then?
Bergi
Oui, uniquement lorsque la promesse de mélange de statuts fulfilledet rejected. Mais en réalité, cela cause un problème difficile à être compatible avec tous les cas d'utilisation de promesse normalement, comme onFulfilledet onRejectedtout retour Promise.reject()ou Promise.resolve(). Jusqu'à présent, je ne sais pas comment le résoudre, quelqu'un a-t-il une meilleure idée? La meilleure réponse pour l'instant a un problème, c'est qu'il ne peut pas filtrer les données et les erreurs dans l'environnement du navigateur.
wenshin
Avons-nous besoin d'installer le module npm avec le gestionnaire de paquets pip python?
sevenfourk