web-dev-qa-db-fra.com

Comment retourner une promesse résolue d'un service AngularJS en utilisant $ q?

Mon service est:

myApp.service('userService', [
  '$http', '$q', '$rootScope', '$location', function($http, $q, $rootScope, $location) {
    var deferred;
    deferred = $q.defer();
    this.initialized = deferred.promise;
    this.user = {
      access: false
    };
    this.isAuthenticated = function() {
      this.user = {
        first_name: 'First',
        last_name: 'Last',
        email: '[email protected]',
        access: 'institution'
      };
      return deferred.resolve();
    };
  }
]);

J'appelle cela dans mon fichier config via:

myApp.run([
  '$rootScope', 'userService', function($rootScope, userService) {
    return userService.isAuthenticated().then(function(response) {
      if (response.data.user) {
        return $rootScope.$broadcast('login', response.data);
      } else {
        return userService.logout();
      }
    });
  }
]);

Cependant, il se plaint que then ne soit pas une fonction. Est-ce que je ne retourne pas la promesse résolue?

44
user3620820

De votre méthode de service:

function serviceMethod() {
    return $timeout(function() {
        return {
            property: 'value'
        };
    }, 1000);
}

Et dans votre contrôleur:

serviceName
    .serviceMethod()
    .then(function(data){
        //handle the success condition here
        var x = data.property
    });
20
Brocco

Comment simplement renvoyer une promesse pré-résolue dans Angular

Promesse résolue:

return $q.when( someValue );    // angular 1.2+
return $q.resolve( someValue ); // angular 1.4+, alias to `when` to match ES6

Promesse rejetée:

return $q.reject( someValue );

Retournez votre promesse, retournez différé.promise.
C'est l'API de promesse qui a la méthode 'then'.

https://docs.angularjs.org/api/ng/service/$q

L'appel à résoudre ne renvoie pas une promesse, il signale seulement la promesse que la promesse est résolue afin qu'il puisse exécuter la logique "then".

Modèle de base comme suit, rincer et répéter
http://plnkr.co/edit/fJmmEP5xOrEMfLvLWy1h?p=preview

<!DOCTYPE html>
<html>

<head>
  <script data-require="angular.js@*" data-semver="1.3.0-beta.5" 
        src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body>

<div ng-controller="test">
  <button ng-click="test()">test</button>
</div>
<script>
  var app = angular.module("app",[]);

  app.controller("test",function($scope,$q){

    $scope.$test = function(){
      var deferred = $q.defer();
      deferred.resolve("Hi");
      return deferred.promise;
    };

    $scope.test=function(){
      $scope.$test()
      .then(function(data){
        console.log(data);
      });
    }      
  });

  angular.bootstrap(document,["app"]);

</script>
34
mccainz

Voici le code correct pour votre service:

myApp.service('userService', [
  '$http', '$q', '$rootScope', '$location', function($http, $q, $rootScope, $location) {

    var user = {
      access: false
    };

    var me = this;

    this.initialized = false;
    this.isAuthenticated = function() {

      var deferred = $q.defer();
      user = {
        first_name: 'First',
        last_name: 'Last',
        email: '[email protected]',
        access: 'institution'
      };
      deferred.resolve(user);
      me.initialized = true;

      return deferred.promise;
    };
  }
]);

Ensuite, votre contrôleur doit s’aligner en conséquence:

myApp.run([
  '$rootScope', 'userService', function($rootScope, userService) {
    return userService.isAuthenticated().then(function(user) {
      if (user) {
        // You have access to the object you passed in the service, not to the response.
        // You should either put response.data on the user or use a different property.
        return $rootScope.$broadcast('login', user.email);  
      } else {
        return userService.logout();
      }
    });
  }
]);

Quelques points à noter sur le service:

  • Exposer dans un service uniquement ce qui doit être exposé. L'utilisateur doit être conservé en interne et être accessible uniquement aux accesseurs.

  • Lorsque vous êtes dans des fonctions, utilisez 'me', le service permettant d'éviter les cas Edge avec javascript.

  • J'ai deviné ce que initialisé était censé faire, n'hésitez pas à me corriger si je me suis trompé.

4
haimlit

Pour retourner une promesse résolue, vous pouvez utiliser:

return $q.defer().resolve();

Si vous devez résoudre quelque chose ou renvoyer des données:

return $q.defer().resolve(function(){

    var data;
    return data;

});
2
Jakub Kozlowski

Pour un code JavaScript plus court, utilisez ceci:

myApp.service('userService', [
  '$q', function($q) {
    this.initialized = $q.when();
    this.user = {
      access: false
    };
    this.isAuthenticated = function() {
      this.user = {
        first_name: 'First',
        last_name: 'Last',
        email: '[email protected]',
        access: 'institution'
      };
      return this.initialized;
    };
  }
]);

Vous savez que vous perdez la liaison à userService.user en la remplaçant par un nouvel objet au lieu de définir uniquement les propriétés de l'objet?

Voici ce que je veux dire comme exemple de mon exemple de code plnkr.co (exemple de travail: http://plnkr.co/edit/zXVcmRKT1TmiBCDL4GsC?p=preview ):

angular.module('myApp', []).service('userService', [
    '$http', '$q', '$rootScope', '$location', function ($http, $q, $rootScope, $location) {
    this.initialized = $q.when(null);
    this.user = {
        access: false
    };
    this.isAuthenticated = function () {
        this.user.first_name = 'First';
        this.user.last_name = 'Last';
        this.user.email = '[email protected]';
        this.user.access = 'institution';
        return this.initialized;
    };
}]);

angular.module('myApp').controller('myCtrl', ['$scope', 'userService', function ($scope, userService) {
    $scope.user = userService.user;
    $scope.callUserService = function () {
        userService.isAuthenticated().then(function () {
            $scope.thencalled = true;
        });
    };
}]);
1
Sebastian

Essaye ça:

myApp.service('userService', [
    '$http', '$q', '$rootScope', '$location', function($http, $q, $rootScope, $location) {
      var deferred= $q.defer();
      this.user = {
        access: false
      };
      try
      {
      this.isAuthenticated = function() {
        this.user = {
          first_name: 'First',
          last_name: 'Last',
          email: '[email protected]',
          access: 'institution'
        };
        deferred.resolve();
      };
    }
    catch
    {
        deferred.reject();
    }

    return deferred.promise;
  ]);
0
premsh