web-dev-qa-db-fra.com

Chaîne Angular $ http appelle correctement?

Je lis sur $ q et promets depuis des jours maintenant et je semble le comprendre ... quelque peu. J'ai la situation suivante en pratique:

  1. Une demande $ http est effectuée et vérifie si un appel ultérieur peut être effectué.
  2. Si le premier appel échoue, retournez "pas de données", s'il réussit et dit qu'un appel peut être effectué, le deuxième appel est fait, sinon - "pas de données" à nouveau. Si le deuxième appel réussit, il renvoie des données, sinon - "pas de données". Cela ressemble à ceci (approximativement, j'ai simplifié pour une idée générale, alors ne vous inquiétez pas des petites erreurs ici):

            return $http.get (something)
                .then(function(allowedAccess){
                    if(allowedAccess){
                        return $http.get (somethingElse)
                            .then( function(result){return {data:result} },
                            function(error){return {data:"n0pe"} }
                        )
                    } else {
                        return {data:"n0pe"}
                    }
                },
                function(){ return {data:"n0pe"} });
    

On m'a dit d'utiliser $ q ici. Je ne comprends pas vraiment comment ni pourquoi je le ferais. Les appels $ http sont déjà des promesses.

S'il existe un moyen de rendre ce produit plus propre, je ne le vois pas. Je viens de finir de relire ce post sur le sujet . Essentiellement, est-ce que je manque quelque chose/y a-t-il une meilleure façon de le faire?

Edit: Aussi, relisez juste n tutoriel sur l'enchaînement des promesses - il ne gère pas du tout les échecs d'appel. Fondamentalement, il s'agit d'une vérification diligente.

Edit 2: Ceci est plus un détail de la théorie que je demande, extrait du premier article:

Ceci est un exemple simple cependant. Il devient vraiment puissant si votre rappel then () renvoie une autre promesse. Dans ce cas, le prochain then () ne sera exécuté qu'une fois cette promesse résolue. Ce modèle peut être utilisé pour les requêtes HTTP série, par exemple (où une requête dépend du résultat d'une précédente):

Cela semble parler de chaînes comme celle-ci:

   asyncFn1(1)
    .then(function(data){return asyncFn2(data)})
    .then(function(data){return asyncFn3(data)})

Donc, si je comprends bien cela a). Ne s'applique pas à moi car je n'ai pas de 3ème fonction. b). S'appliquerait à moi si j'avais trois fonctions car pendant que j'exécute une instruction if à l'intérieur de la première demande $ http, et uniquement à l'intérieur de l'instruction if, je renvoie une autre promesse. Donc, théoriquement, si j'avais trois fonctions asynchrones à enchaîner, j'aurais besoin de mettre ma déclaration if dans une promesse?

17
VSO

Les promesses aident vraiment à la composition du code pour passer des appels asynchrones. En d'autres termes, ils vous permettent de composer votre code de la même manière que vous composeriez un ensemble d'appels synchrones (avec l'utilisation de .then S enchaînés) et comme si le code de synchronisation était dans un try/catch bloc (avec .catch).

Alors, imaginez que vos appels HTTP bloquaient - la logique que vous avez ressemblerait à ceci:

var allowedAccess, data;
try {
  allowedAccess = $http.get(something);

  if (allowedAccess){
    try{
      var result = $http.get(somethingElse);
      data = {data: result};
    } catch (){
      data = {data: "n0pe"};
    }
  } else {
    data = {data: "n0pe"};
  }
} catch (){
  data = {data: "n0pe"};
}
return data;

Vous pourriez simplifier un peu:

var allowedAccess, result;
try {
  allowedAccess = $http.get(something);
  var result;
  if (allowedAccess) {
     result = $http.get(somethingElse);
  } else {
     throw;
  }
  data = {data: result};
} catch () {
   data = {data: "n0pe"};
}
return data;

Et cela se traduirait par la version asynchrone de:

return $http
          .get(something)
          .then(function(allowedAccess){
             if (allowedAccess){
               return $http.get(somethingElse);
             } else {
               return $q.reject(); // this is the "throw;" from above
             }
          })
          .then(function(result){
             return {data: result};
          })
          .catch(function(){
             return {data: "n0pe"};
          })

C'est du moins le raisonnement que vous pourriez appliquer lors de la composition de code avec des branches et des appels asynchrones.

Je ne dis pas que la version que j'ai présentée est optimale ou plus courte - elle est , cependant, plus DRY en raison d'une seule gestion des erreurs. Mais sachez simplement que lorsque vous effectuez .then(success, error), cela équivaut à try/catch par rapport à l'opération asynchrone précédente - cela peut être nécessaire ou non en fonction de votre situation spécifique.

13
New Dev

Voici comment je coderais ce genre de problème:

// returns a promise that resolves some endpoint if allowed
function getDataWithAccess(allowed){
    return allowed ? $http.get(someEndpoint) : $q.reject();
}

// do something with data
function handleData(data){
    // do stuff with your data
}

// main chain
$http.get(accessCredEndpoint)
    .then(getDataWithAccess)
    .then(handleData)
    .catch(function(err){
        return { data: "n0pe" };
    });

Oui, cela ressemble beaucoup à la réponse de New Dev, mais je tenais à extraire les fonctions dans leurs propres blocs. Cela rend le code global beaucoup plus lisible.

7
Matt Way