1
votes

Que se passera-t-il lorsque return new Promise ((résoudre, rejeter) => {}) a oublié d'appeler résoudre ou rejeter?

Le problème est comme celui-ci

function demo() {
    return new Promise((resolve, reject) => {
        ...
        // The problem here!!
        //I just found in some rare case we failed to call resolve or reject
    })
}

demo()
    .then(res => {
        console.log('resolve')
        console.log(res)
    })
    .catch(rej => {
        console.log('reject')
        console.log(rej)
    })
    .finally(() => {
        console.log('why')
    })

Quand j'ai échoué à appeler la résolution ou le rejet, même le bloc finally n'est pas appelé! Pourquoi?

J'avais pensé que c'était un bogue, puis j'ai trouvé que l'auteur original semblait le faire exprès que s'il n'appelait pas résoudre ou rejeter, aucun des éléments de alors / catch / finally ne devrait être appelé, c'est-à-dire que dans ce cas, aucune action de suivi ne doit être entreprise.

Mais est-ce un moyen valable de gérer la situation où aucune action de suivi ne doit être entreprise? Cela causera-t-il des problèmes?

----- update -----

Même si ma question a été marquée comme dupliquée, je ne suis toujours pas satisfait des réponses que j'ai obtenues. Au départ, j'avais pensé que c'était une mauvaise idée de laisser la promesse rester en suspens pour toujours.

Mais la réponse dans cette SO disait: "Il ne devrait y avoir aucun effet secondaire."
La promesse jamais résolue provoque-t-elle une fuite de mémoire? a également dit "En bref - au moins dans les navigateurs modernes - vous n'avez pas à vous soucier des promesses non résolues tant que vous n'avez pas de références externes à celles-ci ". Il semble donc normal de laisser la promesse en suspens si tel est le but.


15 commentaires

Oui, c'est comme prévu - si ni résoudre ni rejet ne sont appelés, la promesse n'a aucune idée que l'action asynchrone est terminée, donc aucun des gestionnaires ne s'attache à l'exécution de la promesse . Mais les promesses qui traînent pour toujours sont une mauvaise idée - mieux vaut corriger le code pour qu'il finisse par se résoudre ou rejeter


Alors "est-ce un moyen valable de gérer la situation où aucune action de suivi ne devrait être prise? Cela causera-t-il des problèmes?"


Je ne pense pas, car ce serait déroutant pour les consommateurs de démo si ni un puis ni un catch ne sont jamais appelés. Mieux vaut résoudre (ou rejeter) quelque chose qui contient des informations indiquant que rien de plus ne doit être fait, je pense, par exemple résoudre ('Aucune action nécessaire')


Alors, y a-t-il un moyen de récupérer ces promesses en suspens?


Uniquement en corrigeant la fonction qui renvoie la promesse - vous devrez refactoriser la démo


Il n'y a pas de moyen simple. Voir par exemple stackoverflow.com/questions/39273680 /… . De préférence, n'utilisez pas du tout new Promise . Même si vous devez le faire, rejetez à l'expiration du délai pour éviter les promesses en attente.


Que fait réellement demo ? Je ne peux pas imaginer un scénario où ne pas résoudre une promesse a du sens.


Je viens de découvrir que dans de rares cas, nous n'avons pas réussi à appeler la résolution ou le rejet , puis, tout simplement, vous faites des erreurs ™


Comme je l'ai dit dans ma question, ma première réaction a été que c'était un bug, puis j'ai trouvé que l'auteur original l'avait fait exprès (d'une manière erronée apparemment). D'où la question.


@Qiulang Qu'entendez-vous par «récupérer»? Ils sont récupérés normalement .


@Bergi merci pour cette SO, mais cette question était: "Les promesses JavaScript toujours en suspens sont-elles mauvaises?" et la réponse acceptée est "Il ne devrait y avoir aucun effet secondaire". Cela signifie-t-il PAS mauvais en soi? Et plus lié à ma question, "est-ce un moyen valable de gérer la situation où aucune mesure de suivi ne devrait être prise". J'avais pensé que la réponse était NON. Mais lorsque vous avez dit que ma question était répétée, avez-vous suggéré que la réponse n'est pas NON? J'étais confus maintenant.


@Qiulang Cela fonctionne (comme vous l'avez vu, rien ne se passe), mais je considérerais quand même que c'est une mauvaise pratique: cela va à l'encontre de la plupart des attentes, comme enfin ne se produisant jamais. C'est aussi mauvais une boucle sans terminaison.


@Bergi merci pour la confirmation. BTW, je ne pense vraiment pas que ma question soit dupliquée avec celle que vous avez mentionnée. Le mien est plus sur la manière appropriée de gérer le "pas d'action de suivi".


@Qiulang Si vous ne voulez absolument aucune action de suivi, ne jamais régler la promesse est la solution. La mauvaise pratique est que vous devez rarement, voire jamais, empêcher les actions de suivi. Quel est votre cas d'utilisation?


@Bergi J'ai examiné plus en détail le code et j'ai réalisé que l'auteur avait fait que b / c le bloc then / finally de la fonction appelante ne gérait pas une situation. Et comme ce bloc then / finally avait été utilisé (copier-coller) à de nombreux endroits, donc au lieu de le réparer à chaque endroit, il a ajouté un correctif à l'endroit qui renvoie la promesse avec l'état en attente, de sorte que l'ancien bloc then / finally n'a pas besoin pour le gérer.


3 Réponses :


1
votes

En interne, une promesse peut être dans l'un des trois états suivants:

En attente , lorsque la valeur finale n'est pas encore disponible. C'est le seul état qui peut passer à l'un des deux autres états. Réalisé , quand et si la valeur finale devient disponible. Une valeur de réalisation devient en permanence associée à la promesse. Il peut s'agir de n'importe quelle valeur, y compris indéfinie. Rejeté , si une erreur a empêché la détermination de la valeur finale. Une raison de rejet devient de façon permanente associée à la promesse. Il peut s'agir de n'importe quelle valeur, y compris indéfinie, bien qu'il s'agisse généralement d'un objet Error, comme dans la gestion des exceptions.

https://developer.mozilla.org /en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Promise

Dans votre cas, la promesse est à l'état en attente et l'appel de la fonction de démonstration attendra toujours que l'état de la promesse soit rempli ou rejeté.


5 commentaires

J'avais pensé que "la fonction appel terminé sera toujours en attente de l'accomplissement ou du rejet du statut de la promesse". Mais j'ai trouvé que la fonction d'appel terminé continue de fonctionner au lieu de rester là.


fonction d'appel terminé Donc, aucun de vous n'a affaire à des promesses, il n'y a pas de fonction done ... puis / catch et plus récemment enfin - les deux derniers étant simplement des variations (sucre) de .then de toute façon


@JaromandaX Je sais qu'il n'y avait pas de fonction terminée, ce que je veux dire, c'est que la fonction d'appel ne s'est pas arrêtée.


c'était en fait une faute de frappe c'est une fonction de démonstration à la place de done


@RajeshKrVerma merci d'avoir répondu mais je ne peux pas rendre votre réponse acceptée car je savais déjà ce que vous avez dit et je ne pense pas que "appeler la fonction de démonstration sera toujours en attente"



0
votes

On s'attend toujours à ce qu'une promesse soit résolue ou rejetée. Si vous avez l'intention de ne pas faire de suivi, vous pouvez résoudre avec un ensemble de données vide ou rejeter avec un code d'erreur qui convient à votre cas d'utilisation.


0 commentaires

0
votes

Vous pouvez utiliser Promise.race pour vérifier si une promesse a été finalisée à temps. Donc, si vous avez oublié d'appeler résoudre ou rejeter dans votre promesse, alors Promise.race sera toujours résolu ou rejeté après un délai.

var promise1 = new Promise(function(resolve, reject) {
    setTimeout(reject, 500);
});

var promise2 = new Promise(function(resolve, reject) {

});

Promise.race([promise1, promise2]).then(function(value) {
  console.log(value);
}).catch(err => console.log('promise rejected'));


0 commentaires