2016-04-19 4 views
1

ich schon asked a question über das Thema verwenden, so ist dies ein Followup in der Tat:Daten vom Server in einem Dienst

ich einen Winkel Service erstellt werden soll, dass, wenn die App zum ersten Mal geladen wird, wird die Daten aus dem Abruf Server einmal und dann kann ich die Daten aus dem lokalen Service-Objekt abfragen. Hier ist, wie ich versuchte, es zu tun:

angular.module('my.services').factory('Properties', function ($http) { 

    var properties = $http.get("/properties"); 

    return { 
    get: function (property) {   
     return properties[property]; 
    } 
    } 
}); 

Problem ist - $http.get() asynchron ist und um zu erreichen, was ich versuche zu tun, ich habe es synchron zu verwenden. Gibt es eine Möglichkeit, dies mit "nativem" AngularJS zu tun? Oder muss ich einen XHR-Anruf dafür verwenden?

Nur zur Klarstellung: Der Unterschied zwischen dieser Frage und der ursprünglichen ist, dass ich nicht nur etwas mit property tun möchte, wie es zum Protokoll drucken. Ich möchte tatsächlich property als Schlüssel zu den Daten verwenden, die vom Server zurückgegeben werden. Wenn die Daten noch nicht da sind, wenn ein Controller get aufruft - möchte ich warten, bis die Daten zurückgegeben werden.

Hier ist, was ich habe jetzt die sehr nicht elegant ist:

return { 
    get: function (property) { 
     while(!properties.$resolved) { 
     setTimeout(function() {}, 2000) 
     } 
     return properties[property]; 
    } 
} 

Antwort

0
angular.module('my.services').factory('Properties', function ($http) { 
    var properties = $http.get("/properties"); 

    return { 
    get: function (property) { 
     properties.then(function(data) { 
     return data[property]; 
     }); 
    } 
    } 
}); 

habe es nicht getestet, aber ich glaube, ‚Eigentum‘ ein Schlüssel in den zurückkehrenden Daten vorhanden sind. Diese

+0

In diesem Fall wird nichts von dem "get" zurückgegeben, denke ich. Liege ich falsch? – Avi

1

:

return properties[property]; 

wird nicht funktionieren. Denken Sie daran, dass properties ein Versprechen ist. Es enthält wahrscheinlich keine Eigenschaft namens property. Sie müssen es so verwenden:

return { 
    get: function (property) {   
     return properties.then(function(response){ 
     return response.data[property]; 
     }) 
    } 
    } 

Dies wird ein Versprechen mit "Eigenschaft" als inneres Ergebnis zurückgeben. Also in Ihrem Controller, verwenden Sie es wie folgt aus:

Properties.get(myProp).then(function(property){ 
    //do something 
}); 

Zweitens zu warten, ein Versprechen zu lösen, bevor der Controller aufgerufen wird (ich bin nicht sicher, ob Sie das wirklich benötigen): Verwenden Sie die resolve Eigenschaft der angular ui router Bibliothek. Mehr Infos hier: https://github.com/angular-ui/ui-router/wiki#resolve

+0

Gibt es keine Möglichkeit zu warten, bis das Eigenschaftsobjekt aufgelöst wird, und die Eigenschaft zurückzugeben, ohne '' '' im Controller zu verwenden? Es macht den Code ohne Grund komplizierter. Ich versuche, einen Dienst zu haben, der Eigenschaften vom Server lädt und sie dann der gesamten App zur Verfügung stellt. Wenn ich jedesmal 'then' aufrufen muss, verkompliziert das die Lesbarkeit des Codes ohne wirklichen Grund. – Avi

+0

Sie könnten die Eigenschaft selbst anstelle des Versprechens zwischenspeichern. Anstatt var properties = $ http ... setzen Sie Eigenschaften, nachdem der http-Aufruf zurückgegeben wurde, und Sie speichern die tatsächlichen Daten in Eigenschaften.Dann können Sie eine Funktion verfügbar machen, die die Eigenschaft zurückgibt, und Sie müssen nicht "dann" im Controller verwenden. Aber der Nachteil ist, dass vor der Verwendung des Controllers, MÜSSEN Sie sicher sein, dass das Versprechen gelöst ist, sonst wird die Funktion nichts zurückgeben. Daher müssen Sie den Parameter resolve auf jedem Controller hinzufügen, der den Service verwendet. Ich denke, die Verwendung von "dann" in der Steuerung ist expliziter. – fikkatra

1

Man könnte es wie folgt tun:

Inject $ q in Ihrem Dienst, dann:

return { 

    get: function(property){ 

    var deferred = $q.defer(); 

    $http.get("/properties").then(function(res){ 

    deferred.resolve(res.data[property]); 

    }).catch(function(err){ 

     //handle error 
     console.log(err); 
     deferred.reject(err) 

     }) 

     return deferred.promise; 

    } 

} 

es dann wie folgt in Ihrem Controller nennen:

Properties.get(prop).then(function(res){ 

    $scope.mydata = res; //or whatever; 

}).catch(function(err){ 

    alert(JSON.stringify(err)); 

})