2014-07-01 2 views
5

ich wie die sauber (und ich denke, leicht zu folgen) Art und Weise, dass Versprechungen autounwrapped wurden:AngularJS - sauberste Weg Versprechen Rahmen hinzuzufügen, jetzt, wo Angular Auto Abwickeln von Versprechen veraltet wirklich

$scope.myData = DataService.query({something:"etc"}); // done; 

Und ich wirklich kümmern sich nicht für das, was jetzt der normale Weg, es zu tun zu sein scheint, ohne die automatische Abwickeln:

DataService.query({something:"etc"}).$promise.then(function (data){ 
    $scope.myData = data; 
}); 

Was ich möchte, um zu sehen, so etwas wie dieses:

$scope.pulseData = $scope.setPromise(CitsciAnalytics.pulse({ 
    projId:"yardmap" 
})); 

Aber ich kann nicht sehen, wie man das macht. Der nächstgelegene ich bekam, war:

$scope.pulseData = $scope.setPromise("pulseData", CitsciAnalytics.pulse({ 
    projId:"yardmap" 
})); 

Mit Hilfe einer Funktion zum Stammbereich hinzugefügt:

.run(["$rootScope", "$log", function ($rootScope, $log) { 
    //parent method to avoid promise unwrapping boilerplate 
    $rootScope.setPromise = function (scopeVar, promise) { 
     if (arguments.length === 2 && promise && promise.$promise) { 
      var scope = this; 
      promise.$promise.then(function (data){ 
       scope[scopeVar] = data; 
      }); 
     } else { 
      $log.error("$rootScope.setPromise has invalid arguments"); 
     } 
    }; 
}]); 

aber Ich mag nicht die unDRY Erfordernis, den Umfang Variablennamen als zusätzliche Zeichenkette mit geben . Hat sich jemand anderes darum gekümmert oder einen Weg gesehen, dies sauberer zu machen?

Antwort

10

Zunächst einmal brauchen Sie nicht

DataService.query({something:"etc"}).$promise.then(function(data){ 
    $scope.myData = data; 
}); 

zu verwenden, die auf eine $resource eindeutig bezeichnet, weil $resource wird ein leeres Array oder Objekt zurückgeben und mit Daten füllen, wie sie ankommen.

Also, mit einer $resource Klasse, können Sie immer noch

$scope.myData = DetaService.query(...); 

$resource ‚s Paradigma verwenden, ist auch ein guter Ansatz in der eigenen "Daten-Abruf" Dienste folgen: Rückkehr und leeres Array und fülle es mit Daten, wenn sie ankommen.

ZB:

.factory('DataService', function ($http) { 
    function query(params) { 
     var data = []; 
     $http.get('/some/url/with/params').then(function (response) { 
      response.data.forEach(function (item) { 
       data.push(item); 
      }); 
     }); 
     return data; 
    } 

    return { 
     query: query 
    }; 
}); 

.controller('someCtrl', function ($scope, DataService) { 
    $scope.data = DataService.query({...}); 

Wenn Sie thrid Anbieter-Dienste nutzen, die ein Versprechen zurückgeben, können Sie Ihre generische Funktion implementieren ähnliche Funktionalität zu bieten:

.run(function ($rootScope) { 
    $rootScope.promiseToArray = function (promise) { 
     var arr = []; 
     promise.then(function (data) { 
      data.forEach(function (item) { 
       arr.push(item); 
      }); 
     }); 
     return arr; 
    }; 
}); 

.controller('someCtrl', function ($scope, ThirdPartyService) { 
    $scope.data = $scope.promiseToArray(ThirdPartyService.fetchData()); 
}); 

Siehe auch diese short demo.


Die oben genannten Beispiele sind nur zum Zwecke Veranschaulichung und nicht produktionsfertige Code.
ich eine reale app, Sie müssten Ausnahmen behandeln, Ablehnungen usw.

+0

ah, vielen Dank für die Klärung, auch was pixelbits vorgeschlagen, schön den offiziellen Weg, um vorwärts zu gehen mit this- – chrismarx

+0

so, für die Menschen $ Ressource verwenden, dies ist nicht wirklich etwas beeinflussen ? https://github.com/angular/angular.js/commit/5dc35b527b3c99f6544b8cb52e93c6510d3ac577 – chrismarx

+0

Genau! Laut ** [die Dokumente] (https://docs.angularjs.org/api/ngResource/service/$resource) **: _ "Es ist wichtig zu erkennen, dass das Aufrufen einer Objektmethode" $ resource "sofort eine zurückgibt leere Referenz (Objekt oder Array abhängig von 'isArray') Sobald die Daten vom Server zurückgegeben werden, wird die vorhandene Referenz mit den tatsächlichen Daten gefüllt.Dies ist ein nützlicher Trick, da die Ressource normalerweise einem Modell zugewiesen wird, das dann von gerendert wird die Ansicht. [...] Dies bedeutet, dass man in den meisten Fällen keine Callback-Funktion für die Aktionsmethoden schreiben muss. "_ – gkalpak

0

Wir können Abwickeln wieder aktivieren, wenn wir wirklich wollen, indem Sie die Option auf true in einer Einstellung.config() Funktion:

.config(function($parseProvider) { 
    $parseProvider.unwrapPromises(true) ; 
});