2016-06-15 8 views
0

Angulars $ Ressource hat große Funktion, um Objekte zurückzugeben, die ihre Werte injiziert bekommen und Ansichten automatisch aktualisieren. Im $ ressource-Service ist ein Resource Objekt, das das aufgelöste Ergebnis in sich selbst kopiert mit shallowClearAndCopy().

Ich möchte die von einer $ -Ressource zurückgegebene Zusage verketten und etwas wie das Resource-Objekt erhalten, das das verzögerte Ergebnis injiziert bekommt. (Code-Beispiel ein Objekt zurückzugeben, bearbeitet und erfordern ein Argument.)

var otherProperty = 'somethingChanging'; 
var lazyUser = $resource('/user/:userId').get({id:id}); 
var userDisplayNamePromise = lazyUser.$promise.then(transformResult); 
function transformResult(user){ 
    return { displayName: user.firstname + ' ' + user.lastname, 
      other: user[otherProperty] 
     }; 
} 

zur Zeit habe ich, wie etwas zu tun

userDisplayNamePromise.then(updateDisplayUser); 
function updateDisplayUser(displayName){$scope.user = displayName;} 

und ich würde so etwas wie

$scope.user = something(userDisplayNamePromise); 
Liebe zu tun

Ich konnte nichts finden, was mir helfen würde, Versprechen so einfach zu nutzen. Hat jemand einen guten Tipp?

Ich habe ein grundlegendes Arbeitsbeispiel bei github.com/burka/resolvling gelegt. Aber ich kann mir nicht vorstellen, dass das vorher niemand gemacht hat?

Antwort

1

Es gibt Standardmethoden, um die Antwort einer Winkelressource zu transformieren.
hier ist ein fiddle
hier ist die documentation

transformResponse - {function (data, headersGetter) |. Array} - Transformationsfunktion oder eine Reihe solcher Funktionen. Die Transformationsfunktion übernimmt den http-Antworttext und die Header und gibt ihre transformierte (in der Regel deserialisierte) Version zurück. Standardmäßig enthält transformResponse eine Funktion, die überprüft, ob die Antwort wie eine JSON-Zeichenfolge aussieht, und sie mithilfe von angular.fromJson deserialisiert. Um dieses Verhalten zu vermeiden, sollten Sie transformResponse auf ein leeres Array: transformResponse: []

hier der Beispielcode ist

angular.module('services', ['ngResource']). 
factory("someService", function ($resource) { 
    return $resource(
     '/', {}, { 
     get: { 
      method: 'GET', 
      transformResponse: function(data, headers){ 
       //MESS WITH THE DATA 
       data = {}; 
       data.coolThing = 'BOOM-SHAKA-LAKA'; 
       return data; 
      } 
     } 
    } 

    ); 
}); 
+0

Ich habe einige verschiedene Transformationen zu tun, abhängig von Daten, die ich der transformierenden Funktion zur Verfügung stellen müsste. Zum Beispiel bekomme ich eine Karte von Gebietsschema-übersetzten Mappings {list1: {a: 1, b: 2}, list2: {d: "Hallo", f: "etwas"}} ', die ich in einer (zwischengespeicherten) Anfrage bekomme brauche aber die Listen in verschiedenen Teilen der App. Also nahm ich den Kartenzugriff auf einen Dienst und wollte ein träge initialisiertes Objekt zurückgeben, anstatt die Verarbeitung von Versprechen zu übernehmen. – flob

+0

Ich habe die Frage entsprechend geändert, indem ich ein Argument hinzugefügt habe, das an die transformierende Funktion übergeben werden müsste. Danke für deine Hilfe :-) Vielleicht muss ich in die Implementierung eintauchen ... :-) – flob

1

Versprechen Defolieren ist eine regelmäßige Routine für die asynchrone Anwendung und sollte als unvermeidlich behandelt werden.

Das Konzept des selbstfüllenden Objekts in $resource ist für asynchronen Arbeitsablauf nicht üblich, abhängig von seiner Verwendung kann es als Antipattern betrachtet werden.

Dies ist nicht möglich, da displayName erwartet wird ein skalarer Wert zu sein:

$scope.displayName = something(userDisplayNamePromise); 

Und das ist etwas, das $q Versprechen nicht ohne ernsthafte Patchwork fähig sind (wie the repo demonstriert):

$scope.displayObj = something(userDisplayNamePromise); 

Während dies funktionieren kann für Objektbindungen wie {{ displayObj.name }}:

$scope.displayObj = userDisplayNamePromise.$$state.value; 

Aber es sollte nicht in der Produktion verwendet werden - nicht nur, weil interne $$ Eigenschaften nicht verwendet werden sollen, sondern auch, weil $$state.value einen Wert für abgelehnte Versprechen enthalten kann.

Für ES6 Umgebung oder Babel-transpiled ES5, co und Generatoren may be used to flatten promises:

var wrap = (fn) => { 
    return function(...args) { 
    co(fn.bind(this, ...args)); 
    } 
} 

app.controller('AppController', ['$scope', '$q', wrap(function* ($scope, $q) { 
    this.name = yield $q.resolve('World'); 
})]); 

Für ngRoute und UI-Router, route Resolvern verwendet werden können, gelöst Werte Controller und binden, die Werte zu Rahmen zu injizieren, diese ist der gebräuchlichste Weg, den Code zu entpacken.

+0

Danke! Ich habe keinen guten Job gemacht, als ich das minimale brauchbare Beispiel lieferte ... Ich habe die Frage aktualisiert, um zu reflektieren, dass ich ein Objekt als Antwort und nicht als unveränderliches Objekt erhalten möchte. – flob

+0

Könnten Sie näher ausführen "Das Konzept des selbstfüllenden Objekts in $ Ressource ist für asynchronen Arbeitsablauf nicht üblich, abhängig von seiner Verwendung kann es als Antipattern betrachtet werden." ? Wenn es ohne Nachdenken verwendet würde, stimme ich zu .. aber ich brauche es nur für einige selbstfüllende übersetzte Dropdown-Optionen, Übersetzungen von Etiketten und Übersetzung einiger Benutzereinstellungen. Alle Werte werden nur durch Winkel angezeigt und nicht weiter verarbeitet. Gibt es weitere Gründe, dies zu vermeiden? – flob

+0

Sind die Blitze von unvorbereitetem Inhalt gesucht? Unwahrscheinlich. Sollte den Benutzern eine halbrunde Ansicht gezeigt werden, wenn eine der Ressourcen verdorben wurde? Zweifelhaft. Dies ist der perfekte Fall für den Routen-/Zustandsresolver. – estus

Verwandte Themen