68 votes

JS angulaire: comment lier aux promesses

Je suis en train de lier une promesse à une vue. Je ne sais pas si vous pouvez le faire directement, mais c'est ce que je tente de faire. Les idées de ce que je fais de mal?

Remarque: la source est un peu artificiel, avec le délai d'attente et utilise des données statiques, mais c'est pour rendre le code plus facile à diagnostiquer.

EDIT: JSFiddle Page: http://jsfiddle.net/YQwaf/27/

EDIT: SOLUTION: Il s'est avéré que vous pouvez lier directement promesses. J'ai eu deux problèmes avec mon code d'origine:

  1. À l'aide de setTimeout() à la place de l'angulaire de l' $timeout a été un problème. Angulaire ne le sait pas besoins d'actualisation de l'INTERFACE utilisateur lorsque la temporisation est déclenchée ( Vous pouvez résoudre ce avec $scope.$appliquer à l'intérieur de setTimeout, ou vous pouvez simplement utiliser $timeout )
  2. La liaison à une fonction qui a retourné une promesse a été un problème. Si elle est appelée une deuxième fois, il fait encore une autre promesse. Le mieux est de définir un champ d'application variable de la promesse et de créer un seul la promesse en tant que de besoin. (Dans mon cas, c'était l'appel de $scope.$montre le Code de Pays)

HTML:

<div ng:controller="addressValidationController">
    Region Code <select ng:model="regionCode" ng:options="r.code as r.name for r in getRegions()"/>
    Country Code<select ng:model="countryCode"><option value="US">United States</option><option value="CA">Canada</option></select>
</div>

JS:

function addressValidationController($scope, $q) {
    var regions = {
        US: [{code: 'WI',name: 'Wisconsin'}, {code: 'MN',name: 'Minnesota'}], 
        CA: [{code: 'ON',name: 'Ontario'}]
    };
    $scope.getRegions = function () {
        var deferred = $q.defer();
        setTimeout(function () {
            var countryRegions = regions[$scope.countryCode];
            console.log(countryRegions);
            if(countryRegions === undefined) {
                deferred.resolve([]);
            } else {
                deferred.resolve(countryRegions);
            }
        }, 1000);
        return deferred.promise;
    };
}

70voto

Dan Points 16670

Depuis Angular 1.2, vous ne pouvez plus utiliser directement les promesses dans les modèles .
Au lieu de cela, vous devez mettre le résultat dans $scope dans then , comme vous le feriez normalement sans magie.

Pour contourner temporairement l’ancien comportement, vous pouvez appeler

 $parseProvider.unwrapPromises(true)
 

mais cette fonctionnalité sera supprimée plus tard, alors ne comptez pas dessus.

29voto

Guillaume86 Points 7812

AVERTISSEMENT: cette réponse est exacte quand elle a été écrite, mais que de 1,2 Angulaire moteur de template ne gère pas les promesses de manière transparente! -- @Malvolio

Oui, le moteur de template (et expressions) poignée de promesses, de manière transparente, mais je voudrais céder la promesse d'une portée de propriété dans le contrôleur, et de ne pas appeler à chaque fois une fonction qui renvoie une nouvelle promesse (je pense que c'est votre problème, résolu promesse est perdue en raison d'une nouvelle promesse est retournée à chaque fois).

JSFiddle: http://jsfiddle.net/YQwaf/36/

HTML:

<div ng:controller="addressValidationController">
    Region Code <select ng:model="regionCode" ng:options="r.code as r.name for r in regions"/>
    Country Code<select ng:model="countryCode"><option value="US">United States</option><option value="CA">Canada</option></select>
</div>

JS:

function addressValidationController($scope, $q, $timeout) {
    var regions = {
        US: [{
            code: 'WI',
            name: 'Wisconsin'},
        {
            code: 'MN',
            name: 'Minnesota'}],
        CA: [{
            code: 'ON',
            name: 'Ontario'}]
    };

    function getRegions(countryCode) {
        console.log('getRegions: ' + countryCode);
        var deferred = $q.defer();
        $timeout(function() {
            var countryRegions = regions[countryCode];
            if (countryRegions === undefined) {
                console.log('resolve empty');
                deferred.resolve([]);
            } else {
                console.log('resolve');
                deferred.resolve(countryRegions);
            }
        }, 1000);
        return deferred.promise;
    };

    $scope.regions = [];

    // Manage country changes:
    $scope.$watch('countryCode', function(countryCode) {
        if (angular.isDefined(countryCode)) {
            $scope.regions = getRegions(countryCode);
        }
        else {
            $scope.regions = [];
        }
    });
}​

27voto

Benjamin Gruenbaum Points 51406

À partir d'angulaires, 1,3 - $parseProvider.unwrapPromises(true) ne fonctionneront plus.

Au lieu de cela, vous devriez ouvrir les promesses directement:

 myApiMethod().then(function(value){
    $scope.item = value; 
});
 

Notez que le déballage des promesses fonctionnera toujours avec ngResource comme d’habitude.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X