web-dev-qa-db-fra.com

En attente d'une promesse?

J'ai le code angularjs suivant:

$scope.clients = commonFactory.getData(clientFactory.getClients());
if ($scope.clients.length > 0) {
    $scope.sampleForm.ClientId = $scope.clients[0].ClientId;
}

Et la fonction getData dans commonFactory:

factory.getData = function (method) {
    method.then(function (response) {
        return response.data;
    }, function (error) {
        $rootScope.alerts.Push({ type: 'error', msg: error.data.ExceptionMessage });
    });
};

Le problème est que $ scope.clients.length n'est pas défini quand il frappe cette ligne à cause de l'appel asynchrone.

Existe-t-il un moyen de ne pas vérifier ma longueur avant de savoir que $ scope.clients a été attribué? J'ai regardé quelque chose comme ça:

$scope.clients = commonFactory.getData(clientFactory.getClients()).then(function () {
    if ($scope.clients.length > 0) {
        $scope.sampleForm.ClientId = $scope.clients[0].ClientId;
    }
});

J'essaie d'enchaîner mes promesses de then, mais pas de dés… le but ici est d'avoir la méthode getData pour éviter un tas de code passe-partout pour attraper les erreurs… peut-être que j'y vais mal?

31
Nicros

C’est la situation la plus fondamentale à laquelle les promesses sont destinées. Vous devez simplement faire une promesse avec var deferred = $q.defer() lorsque vous commencez une opération asynchrone, résolvez-la avec deferred.resolve(result) lorsque l'opération asynchrone est terminée et renvoyez deferred.promise Dans votre fonction. . Les méthodes asynchrones d'Angular effectuent cela en interne et renvoient déjà des promesses. Vous pouvez donc simplement renvoyer ces mêmes promesses au lieu de créer de nouvelles promesses avec $q.defer(). Vous pouvez joindre un .then À tout ce qui retourne une promesse. De plus, si vous retournez une valeur à partir d'une fonction then, cette valeur sera encapsulée dans une promesse afin que la chaîne then puisse continuer.

angular.module('myApp', [])

.factory('myService', function($q, $timeout, $http) {
  return {
    myMethod: function() {
      // return the same promise that $http.get returns
      return $http.get('some/url');
    }
  };
})

.controller('myCtrl', function($scope, myService) {
  myService.myMethod().then(function(resp) {
    $scope.result = resp.data;
  });
})

Et voici un peu plus de plaisir avec le chaînage:

.factory('myService', function($q, $timeout, $http) {
  return {
    myMethod: function() {
      // return the same promise that $http.get returns
      return $http.get('some/url').then(function() {
        return 'abc';
      });
    }
  };
})

.controller('myCtrl', function($scope, myService) {
  myService.myMethod().then(function(result) {
    console.log(result); // 'abc'
    return someOtherAsyncFunc(); // for example, say this returns '123'
  }).then(function(result) {
    console.log(result); // '123'
  });
})
34
m59