1
votes

Est-il possible d'annuler une promesse enfant lorsque le parent est annulé?

J'ai ce code (en utilisant Bluebird Promise):

const promise = loadSomething(id)
  .then(something => {
    loadParentOfSomething(something.parentId);
    return something;
  });

Quand je fais ensuite promise.cancel () le getSomething est annulé, mais le getSomethingParent ne l'est pas.

Y a-t-il un moyen de, lorsque la promesse getSomething est annulée, je peux également obtenir le getSomethingParent promesse d'annuler?

Les deux fonctions de chargement renvoient une promesse asynchrone annulable avec une requête HTTP, et la raison pour laquelle je veux les annuler est qu'elles peuvent parfois prendre un certain temps à se charger et quand, par exemple un utilisateur s'éloigne (SPA), la réponse n'est plus nécessaire.


7 commentaires

getSomethingParent () est-il une tâche asynchrone qui peut être annulée du tout? Cela ressemble à peu près à une fonction synchrone maintenant - et vous ne faites rien avec son résultat.


Oui, il renvoie également une promesse annulable. Désolé, cela aurait dû être plus clair.


Mais vous ne faites rien avec cette promesse (mais vous la jetez)? Ne recevez-vous pas un avertissement Bluebird à ce sujet ?


Pas que j'ai vu. C'est une promesse qui déclenche finalement un événement chargé via un magasin, alors il fait quelque chose. Pas juste là.


… Et à cause de cela, promise ne le sait pas et n'est pas incité à l'annuler.


Exactement, donc je cherche un moyen de faire des promesses en quelque sorte le savoir afin qu'il puisse le faire tomber avec lui.


Voir ma réponse sur la façon de faire cela. Ou est-ce que cela ne fait pas ce que vous voulez?


3 Réponses :


-1
votes

Définissez une fonction comme deuxième paramètre du rappel puis . Exemple:

const promise = getSomething(id)
  .then(something => {
    getSomethingParent(something.parentId);
    return something;
  }, error => {
    console.error(error)
  });

Lorsque vous appelez promise.reject () , alors getSomethingParent ne sera pas appelé. Référence


7 commentaires

Cependant, getSomethingParent a déjà été appelé. Ainsi, la promesse getSomething a déjà été tenue, mais pas getSomethingParent . J'aimerais que getSomethingParent soit annulé lorsque cancel est appelé, quel que soit l'état de getSomething . Si ça a du sens. 🤔


Non, il ne sera appelé que lorsque getSomething sera terminé. C'est pourquoi il est placé dans le puis .


Si la promesse getSomething a été tenue, comment l'annulez-vous?


Que des erreurs soient détectées n'a absolument rien à voir avec getSomethingParent ou même avec l'annulation en général.


@Bergi par défaut si une fonction d'erreur n'est pas définie, le rappel then est appelé à la fois en cas de succès et d'erreur. Donc, si l'utilisateur veut gérer les cas où la promesse est rejetée , la définition d'une fonction d'erreur aidera. Voici une référence


@varunagarwal Euh, non. Vous devez avoir horriblement mal compris cette documentation. À quelle phrase faites-vous référence spécifiquement, peut-être que je peux corriger le wiki pour clarifier cela?


Oups mon mal. Désolé pour ça.



-2
votes

Si vous préparez une promesse factice pour référencer loadSomethingOfParent , vous devriez pouvoir l'annuler dans loadSomething.

function loadSomething(id, promise) {
  return new Promise(function(resolve, reject, onCancel) {
    // Do your stuff

    // The `.cancel()` handler
    onCancel(function() {
      promise.cancel();
    });
  });
}

loadSomething aura besoin d'un gestionnaire onCancel qui s'exécutera lorsque la promesse sera annulée.

// Create a dummy promise to reference `loadParentOfSomething`
var dummyPromise = Promise.resolve(); 

// Pass `dummyPromise` to `loadSomething`
const promise = loadSomething(id, dummyPromise).then(something => {
  dummyPromise = loadParentOfSomething(something.parentId);
  return something;
});


1 commentaires

Cela ne fonctionne pas - promise dans loadSomething fera toujours référence à la promesse factice Promise.resolve () , pas à son remplacement. JS n'a pas de pass-by-reference. Je doute également que le rappel onCancel soit exécuté après la promesse loadSomething () appelée résoudre / rejet .



0
votes

Je pense que ce que vous recherchez réellement

const promise1 = loadSomething(id);
const promise2 = promise1.then(something => { return loadParentOfSomething(something.parentId); });
//                                            ^^^^^^
promise2.catch(e => void "ignore"); // prevent unhandled rejections

Ensuite, vous pouvez continuer à utiliser promise1 pour accéder au résultat, mais aussi appeler promise2.cancel ( ) . Cette annulation sera possible même après le règlement de promise1 .


3 commentaires

En fait, j'ai essayé de le faire, mais cela ne semblait pas faire de différence, alors peut-être qu'il se passait autre chose ici. 🤔


… Ou peut-être que je ne comprends pas comment l'annulation de Bluebird fonctionne réellement. Attendons que Benjamin Gruenbaum vienne et confirme.


J'ai réussi à le contourner en ne faisant pas ce chargement parent car il s'est avéré que les données parentales revenaient en fait dans le cadre de something.parent . Je pensais que c'était juste un petit extrait de code, mais après l'avoir examiné un peu plus, il s'agissait en fait à peu près des mêmes données que celles provenant de loadParentOfSomething . Mais oui, ce serait formidable si quelqu'un pouvait faire la lumière sur cette annulation, car je pense vraiment que cela aurait dû fonctionner comme ça. 😕