2013-02-15 4 views
13

Die Erfolgsfunktion von $http.put hat keinen Zugriff auf den Bereich this des Dienstes, der innerhalb aufgerufen wird. Ich muss eine Eigenschaft des Dienstes im Rückruf von der PUT-Anfrage aktualisieren.AngularJS-Service http-Erfolgsfunktion mit falschem "diesem" Gültigkeitsbereich

Dies ist ein abgespeckte Beispiel dafür, was ich versuche, in einem Dienst zu tun:

var myApp = angular.module('myApp', function($routeProvider) { 
// route provider stuff 
}).service('CatalogueService', function($rootScope, $http) { 
    // create an array as part of my catalogue 
    this.items = []; 

    // make a call to get some data for the catalogue 
    this.add = function(id) { 
     $http.put(
      $rootScope.apiURL, 
      {id:id} 
     ).success(function(data,status,headers,config) { 
      // on success push the data to the catalogue 
      // when I try to access "this" - it treats it as the window 
      this.items.push(data); 
     }).success(function(data,status,headers,config) { 
      alert(data); 
     }); 
    } 
} 

Sorry, wenn es einige Fehler in der JS ist, ist der wichtigste Punkt, wie greife ich auf den Umfang Service von innerhalb des Erfolgs Rückruf?

EDIT: Während die Antwort auf diese Frage richtig war, wechselte ich auf die factory Methode sowohl als Josh und Mark empfohlen es

Antwort

15

einen Verschluss über eine Variable erstellen (oft that genannt), die auf this zugeordnet, so dass Ihre Callback-Funktionen Zugriff auf Ihre Service-Objekt haben:

app.service('CatalogueService', function($rootScope, $http) { 
    var that = this; 
    ... 
     ).success(function(data,status,headers,config) { 
      that.items.push(data); 

Hier ist ein Plunker, die stattdessen $ timeout verwendet von $ http zu demonstrieren.

+4

Ich mag immer noch die Factory-Methode in diesem Fall besser, aber +1 für die tatsächliche Beantwortung der Frage. :-) –

+0

@Josh, ich bevorzuge die Fabrik auch. –

+0

Ich werde mit der Fabrik Antwort gehen, aber ich fühle mich wie ich sollte dies als die richtige Antwort wählen, wie es die Frage beantwortet. Ich werde sicherlich eine Bearbeitung zu meiner Frage hinzufügen, um zu erwähnen, dass ich auf Ihre Frage zurückgegriffen habe @JoshDavidMiller –

23

Soweit ich weiß, kann man nicht. Aber ich würde sowieso nicht versuchen, den Dienst so zu führen. Hier ist ein sauberer Weg:

.factory('CatalogueService', function($rootScope, $http) { 
    // We first define a private API for our service. 

    // Private vars. 
    var items = []; 

    // Private methods. 
    function add(id) { 
    $http.put($rootScope.apiURL, {id:id}) 
    .success(function(data,status,headers,config) { items.push(data); }) 
    .then(function(response) { console.log(response.data); }); 
    } 

    function store(obj) { 
    // do stuff 
    } 

    function remove(obj) { 
    // do stuff 
    } 

    // We now return a public API for our service. 
    return { 
    add: add, 
    store: store, 
    rm: remove 
    }; 
}; 

Dies ist ein sehr häufig Muster von Dienstleistungen in AngularJS entwickeln und es erfordert keine Verwendung von this in diesen Fällen.

+0

Ich versuche den Unterschied zwischen einem Service und einer Fabrik zu verstehen, aber ich dachte, Fabriken sollten sich selbst zurückgeben, und Dienstleistungen waren nicht: http://StackOverflow.com/Questions/13762228/confused- about-service-vs-factory –

+0

Als ich Ihren Code kopiert und eingefügt habe, habe ich vergessen, ihn in '.factory' zu ändern. Ich habe die Antwort aktualisiert. Dienste werden mit einer von mehreren Modulmethoden erstellt. 'factory' gibt zurück, was Sie wollen und' service' nimmt nur einen Konstruktor, der vom Provider ausgeführt wird, der das neue Objekt zurückgibt. Ohne auf JavaScript-Magie zurückgreifen zu müssen, sollten Sie 'factory' verwenden, um Ergebnisse von asynchronen Operationen zu speichern. –

+0

Ok, also habe ich das 'Items'-Problem, indem ich mache, was Sie oben beschrieben haben, aber jetzt bekomme ich das gleiche Problem, wenn ich versuche, eine andere Methode als die Factory im Erfolgs-Callback aufzurufen. Ich lade einige Daten herunter, und wenn es erfolgreich heruntergeladen wird, möchte ich eine 'store()' Methode aufrufen, um diese in localStorage zu schreiben. In Ihrem Codebeispiel wäre es so, als würde man zum Beispiel die Methode 'get()' aufrufen. –

Verwandte Themen