webentwicklung-frage-antwort-db.com.de

Angular JS: wie man sich an Versprechen bindet

Ich versuche, ein Versprechen an eine Ansicht zu binden. Ich weiß nicht, ob Sie das direkt tun können, aber ich versuche es. Irgendwelche Ideen, was ich falsch mache?

Hinweis: Die Quelle ist ein wenig mit dem Timeout verbunden und verwendet statische Daten. Dies erleichtert jedoch die Diagnose des Codes.

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

EDIT: SOLUTION: Es stellte sich heraus, dass Sie can Versprechen direkt binden können. Ich hatte zwei Probleme mit meinem ursprünglichen Code:

  1. Die Verwendung von setTimeout () anstelle des $ Timeout von Anglees war ein Problem. Angular weiß nicht, dass es erforderlich ist, die Benutzeroberfläche zu aktualisieren, wenn das Timeout ausgelöst wird (Sie können dies mit $ scope lösen. $ Innerhalb von setTimeout anwenden oder einfach $ timeout verwenden)
  2. Die Bindung an eine Funktion, die ein Versprechen zurückgegeben hat, war ein Problem. Wenn es ein zweites Mal aufgerufen wird, gibt es noch ein weiteres Versprechen. Besser ist es, eine Gültigkeitsvariable auf das Versprechen zu setzen und nur bei Bedarf ein neues Versprechen zu erstellen. (In meinem Fall war dies der Aufruf von $ scope. $ Watch auf dem Ländercode)

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;
    };
}
64
Adam Tegen

WARNING: Diese Antwort war korrekt, als sie geschrieben wurde, aber ab 1.2 kann die Angular Template Engine Versprechen nicht transparent behandeln! - @Malvolio

Ja, die Vorlagen-Engine (und die Ausdrücke) behandeln Versprechen transparent, aber ich würde das Versprechen einer Bereichseigenschaft im Controller zuweisen und nicht jedes Mal eine Funktion aufrufen, die ein neues Versprechen zurückgibt (Ich denke, es ist Ihr Problem, das gelöste Versprechen geht verloren, weil ein neues verloren geht Versprechen wird jedes Mal zurückgegeben).

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 = [];
        }
    });
}​
29
Guillaume86

Ab Angular 1.2 können Sie Versprechen nicht mehr direkt in Vorlagen verwenden .
Stattdessen müssen Sie das Ergebnis wie üblich in $scope in then einfügen - keine Magie.

Als vorübergehende Problemumgehung können Sie das alte Verhalten aufrufen

$parseProvider.unwrapPromises(true)

diese Funktion wird jedoch später entfernt, also hängen Sie nicht davon ab.

71
Dan Abramov

Ab Angular 1.3 funktioniert $parseProvider.unwrapPromises(true)nicht mehr .

Stattdessen sollten Sie die Versprechen direkt auspacken:

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

Beachten Sie, dass das Versprechen des Versprechens wie üblich mit ngResource funktioniert.

27

die Rückgabe einer Referenz auf die Gültigkeitsbereichsvariable, die die Liste enthält, sollte ausreichen.

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

    $scope._regions = [];

    $scope.getRegions = function () {

        $timeout(function () {
            var countryRegions = regions[$scope.countryCode];
            console.log(countryRegions);
            if(countryRegions === undefined) {
                $scope._regions = []
            } else {
                $scope._regions = countryRegions
            }
        }, 1000);

        return $scope._regions;
    };
}
0
David Fulgham