web-dev-qa-db-fra.com

Utilisation de success / error / finally / catch avec Promises dans AngularJS

J'utilise $http dans AngularJs et je ne suis pas sûr de la façon d'utiliser la promesse retournée et de gérer les erreurs.

J'ai ce code:

$http
    .get(url)
    .success(function(data) {
        // Handle data
    })
    .error(function(data, status) {
        // Handle HTTP error
    })
    .finally(function() {
        // Execute logic independent of success/error
    })
    .catch(function(error) {
        // Catch and handle exceptions from success/error/finally functions
    });

Est-ce une bonne façon de le faire ou existe-t-il un moyen plus simple?

109
Joel

Les promesses sont une abstraction sur des déclarations qui nous permettent de nous exprimer de manière synchrone avec du code asynchrone. Ils représentent une exécution d'une tâche ponctuelle.

Ils fournissent également une gestion des exceptions, tout comme le code normal, vous pouvez revenir d'une promesse ou vous pouvez lancer.

Ce que vous voudriez en code synchrone est:

try{
  try{
      var res = $http.getSync("url");
      res = someProcessingOf(res);
  } catch (e) {
      console.log("Got an error!",e);
      throw e; // rethrow to not marked as handled
  }
  // do more stuff with res
} catch (e){
     // handle errors in processing or in error.
}

La version promise est très similaire:

$http.get("url").
then(someProcessingOf).
catch(function(e){
   console.log("got an error in initial processing",e);
   throw e; // rethrow to not marked as handled, 
            // in $q it's better to `return $q.reject(e)` here
}).then(function(res){
    // do more stuff
}).catch(function(e){
    // handle errors in processing or in error.
});
97

Oubliez l'utilisation de la méthode success et error.

Les deux méthodes sont obsolètes dans angular 1.4. En gros, la raison de la dépréciation est qu’ils ne sont pas faciles à chaîner , pour ainsi dire.

Avec l'exemple suivant, je vais essayer de montrer ce que je veux dire par success et error n'étant pas chainable-friendly . Supposons que nous appelions une API qui renvoie un objet utilisateur avec une adresse:

Objet utilisateur:

{name: 'Igor', address: 'San Francisco'}

Appel à l'API:

$http.get('/user')
    .success(function (user) {
        return user.address;   <---  
    })                            |  // you might expect that 'obj' is equal to the
    .then(function (obj) {   ------  // address of the user, but it is NOT

        console.log(obj); // -> {name: 'Igor', address: 'San Francisco'}
    });
};

Que s'est-il passé?

Parce que success et error retournent la promesse originale , c'est-à-dire celle renvoyée par $http.get, l’objet passé au callback de la then est l’ensemble de l’utilisateur , c’est-à-dire de la même entrée que le précédent success rappel.

Si nous avions enchaîné deux then, cela aurait été moins déroutant:

$http.get('/user')
    .then(function (user) {
        return user.address;  
    })
    .then(function (obj) {  
        console.log(obj); // -> 'San Francisco'
    });
};
42
Michael P. Bazos

Je pense que les réponses précédentes sont correctes, mais voici un autre exemple (juste un f.y.i, success () et error () sont déconseillés selon AngularJS Page principale :

$http
    .get('http://someendpoint/maybe/returns/JSON')
    .then(function(response) {
        return response.data;
    }).catch(function(e) {
        console.log('Error: ', e);
        throw e;
    }).finally(function() {
        console.log('This finally block');
    });
35
grepit

Quel type de granularité recherchez-vous? Vous pouvez généralement vous en tirer avec:

$http.get(url).then(
  //success function
  function(results) {
    //do something w/results.data
  },
  //error function
  function(err) {
    //handle error
  }
);

J'ai trouvé que "finalement" et "attrapé" sont mieux à utiliser lors de l'enchaînement de plusieurs promesses.

11
justin

Dans le cas Angular $ http, la fonction success () et error () aura un objet de réponse non déballé, la signature de rappel sera donc comme $ http (...). Success (fonction (données, statut , en-têtes, config))

pour then (), vous aurez probablement affaire à l'objet de réponse brut. tel que posté dans le document API AngularJS $ http

$http({
        url: $scope.url,
        method: $scope.method,
        cache: $templateCache
    })
    .success(function(data, status) {
        $scope.status = status;
        $scope.data = data;
    })
    .error(function(data, status) {
        $scope.data = data || 'Request failed';
        $scope.status = status;
    });

La dernière .catch (...) n'aura pas besoin à moins qu'il y ait une nouvelle erreur jetée dans la chaîne de promesse précédente.

5
zd333