Je travaille sur une chaîne de promesses inspirée de cette réponse: https://stackoverflow.com/a/44955506/7485805
Je veux interrompre cette boucle for afin de gérer correctement le rejet de la chaîne. Je viens de me dire que je ne peux pas utiliser break
dans la méthode .catch
de la chaîne.
Voici mon code si cela aide: p >
.then(() => { if(i === (length - 1) ) resolve(); })
x, y, z
sont trois fonctions enchaînées dans la fonction pro
Tandis que x
se résout avec succès, y
est exécuté mais est rejeté.
Je veux arrêter l'exécution de z
depuis il est inutile de continuer et peut produire une erreur dans le code réel.
De plus, si quelqu'un peut me recommander une meilleure version pour ce morceau de code:
function pro (arr) { let chain = Promise.resolve(); const self = {req: {}, res: {}}; const length = arr.length; return new Promise((resolve, reject) => { for(let i=0; i<length; i++){ chain = chain .then(() => arr[i].call(self) ) .then(() => { if(i === (length - 1) ) resolve(); }) .catch(e => { reject(e); }) } }) .then(() => { return self }) .catch(e => { throw new Error (e); }) } const x = function () { const self = this; return new Promise(resolve => { self.req = {key: "value"} resolve(); }) } const y = function () { const self = this; return new Promise((resolve, reject) => { console.log(self); reject(); }) } const z = function () { const self = this; return new Promise((resolve, reject) => { console.log('failed'); }) } pro([x, y, z]) .then((self) => { console.log('final',self); }) .catch(e => { console.log('error', e); })
Remarque: je ne peux pas utiliser await
car ce code sera exécuté côté serveur et l'utilisation de await
peut bloquer d'autres requêtes entrantes.
3 Réponses :
C'est beaucoup plus facile à faire avec la syntaxe async / await
:
async function pro(arr) { const self = {req: {}, res: {}}; for(const f of arr) await f.call(self); return self; } const x = function () { const self = this; return new Promise(resolve => { self.req = {key: "value"} resolve(); }) } const y = function () { const self = this; return new Promise((resolve, reject) => { console.log(self); reject("y failed"); }) } const z = function () { const self = this; return new Promise((resolve, reject) => { console.log('failed'); }) } pro([x, y, z]).then((self) => { console.log('final',self); }) .catch(e => { console.log('error', e); });
async function pro(arr) { const self = {req: {}, res: {}}; for(const f of arr) await f.call(self); return self; }
Êtes-vous sûr que l'utilisation de await
ne bloquera pas les autres requêtes entrantes sur le serveur de nœuds?
Non, wait
ne bloque pas . Cela rend la fonction retour immédiatement avec une promesse. Son contexte est rétabli lorsque cette promesse se résout.
Quelques petites choses: lorsque vous construisez votre chaîne de promesses à l'intérieur d'une boucle for, c'est tout ce qui se passe: la chaîne est construite. L'exécution de .then
aura lieu au plus tôt dans la prochaine boucle d'événements. Je vais essayer d'illustrer:
var promiseChain = functionReturningPromise(); for(var i=0;i<3;i++){ promiseChain = promiseChain.then(x=> { return anotherPromiseFunction(x); }); }
En fonction de ce que fait réellement functionReturningPromise
, quelque chose s'est peut-être déjà produit à ce stade ... ou peut-être pas. Par exemple, nous avons peut-être commencé une fetch
, ou peut-être lancé un WebWorker.
Cependant, si nous avions un setTimeout
imbriqué à l'intérieur de la première promesse, alors tout ce que nous avons fait a été de mettre le rappel setTimeout
dans la file d'attente pour le prochain cycle de la boucle d'événements. Mais garanti à 100%, aucune fonction .then
n'est encore exécutée. Cela vient plus tard, dans la prochaine boucle d'événements.
La prochaine boucle d'événements arrive et la promesse est résolue. Cela signifie que le prochain .then
sera exécuté. Disons que cela échoue. À ce stade, parce que nous avons enchaîné les promesses ( promiseChain = promiseChain.then
), nous passons immédiatement au premier .catch
(ou .then
avec un deuxième paramètre) dans la chaîne, et tous les .then
intervenant sont complètement ignorés sans être exécutés. Ou s'il n'y a pas de catch
es, alors cette chaîne de promesse est terminée. Aucune pause nécessaire; c'est juste la façon dont les promesses fonctionnent.
Donc, si vous ajoutez simplement un .catch
à la toute fin de la chaîne, vous êtes bon.
À propos de ça chose "boucle d'événement": Je recommande vraiment de regarder Jake Archibald: dans The Loop , de JSConf.Asia 2018.
Aussi à propos de await
... On dirait qu'il y a une certaine confusion sur son fonctionnement. Vous ne pouvez utiliser wait
que dans une fonction async
, vous ne pouvez donc jamais bloquer complètement l'exécution du thread avec un seul wait
. Cela fonctionne comme le chaînage de .puis
, juste du sucre syntaxique. Donc, @trincot a définitivement raison, vous serez beaucoup plus satisfait de cette syntaxe.
J'aime vraiment l'explication ici. Merci beaucoup. De plus, vous venez de dissiper mes doutes sur wait
et je vais certainement regarder le lien JSConf.
Voici une réponse alternative qui exécute simplement les promesses les unes après les autres, sauf si une promesse a été rejetée qui est ensuite arrêtée. Cela n'utilise pas await mais cela devrait vous donner une idée générale de la façon dont cela pourrait être fait sans lui, mais ce code a également été écrit très rapidement, ce n'est donc pas le code le plus optimisé.
const x = function() { return new Promise(resolve => { resolve('it resolved ma!'); }); }; const y = function() { const self = this; return new Promise((resolve, reject) => { reject("reject"); }); }; const z = function() { const self = this; return new Promise((resolve, reject) => { resolve("never gets executed"); }); }; function runPromises(promises) { const results = []; let count = 0; const executePromise = i => { count++; return promises[i]() .then((response) => { results.push(response); if (count !== promises.length) { executePromise(count); } }) .catch((e) => { results.push(e); console.log("stop right now, thank you very much"); }); }; if (Array.isArray(promises)) { executePromise(count); } return results; } const results = runPromises([x, y, z]); console.log(results);
"Je veux interrompre cette boucle for" Voir cette réponse à Exécutez plusieurs promesses récursives et interrompez-les sur demande . Pourquoi la boucle doit-elle être interrompue pour gérer une erreur? Que signifie "break" dans le contexte?
@Bergi Veuillez consulter le lien: es6console.com/jsjdb5rx
" y est exécuté mais est rejeté, je veux arrêter l'exécution de z " - euh, si vous avez construit votre chaîne de la même manière que dans la réponse que vous avez liée, alors
z
n'est pas exécuté du tout?! Votre problème est que.catch (e => {refuse (e);})
qui ne gère pas réellement l'erreurÉvitez la
Promise code> anti-modèle du constructeur
!Est-ce cela ce que vous essayez d'accomplir?