2016-06-04 3 views
7

Zur Zeit habe ich Anrufe wie diese alle über meine drei Controller:

$scope.getCurrentUser = function() { 
    $http.post("/Account/CurrentUser", {}, postOptions) 
     .then(function(data) { 
       var result = angular.fromJson(data.data); 
       if (result != null) { 
        $scope.currentUser = result.id; 
       } 
      }, 
      function(data) { 
       alert("Browser failed to get current user."); 
      }); 
}; 

ich viele Ratschläge sehen die $http Anrufe in ein Httpservice zu verkapseln, oder so, aber das ist es viel besser Praxis das Versprechen zurückzukehren als die Daten zurückgeben. Doch wenn ich wieder das Versprechen, alle bis auf eine Linie in meinem Controller $http Anrufs ändert, und die gesamte Logik mit der Antwort des Umgangs bleibt in meinem Controller, zB:

$scope.getCurrentUser = function() { 
    RestService.post("/Account/CurrentUser", {}, postOptions) 
     .then(function(data) { 
       var result = angular.fromJson(data.data); 
       if (result != null) { 
        $scope.currentUser = result.id; 
       } 
      }, 
      function(data) { 
       alert("Browser failed to get current user."); 
      }); 
}; 

ich einen RestService für jede Server-Seite erstellen können Controller, aber das würde nur einen Core-Service aufrufen und die URL trotzdem weitergeben.

+1

möglich doppelte http://stackoverflow.com/questions/17646034/what-is-the-best-practice-for-making-an-ajax-call-in-angular-js – jbe

+0

Vorteile von Dienstleistungen an: einfache Wiederverwendung Code , einfache Controller- und Servicetests, einfacher Service-Spott. – dfsq

Antwort

2

Es gibt einige Gründe, warum es in nicht-trivialen Anwendungen gut ist.

Die Verwendung eines einzigen generischen Dienstes und das Eingeben der URL und der Parameter fügt nicht so viel Wert hinzu, wie Sie bemerkt haben. Stattdessen müssen Sie für jede Art von Abruf eine Methode verwenden.

Einige Vorteile der Dienste:

  • Wiederverwendbarkeit. In einer einfachen App kann für jeden Controller ein Datenabruf erfolgen. Aber das kann sich bald ändern. Sie haben beispielsweise eine Produktlistenseite mit getProducts und eine Detailseite mit getProductDetail. Dann möchten Sie jedoch eine Verkaufsseite, eine Kategorieseite oder verwandte Produkte auf der Detailseite hinzufügen. Diese könnten alle die ursprünglichen getProducts (mit entsprechenden Parametern) verwenden.
  • Testen. Sie möchten den Controller isoliert von einer externen Datenquelle testen können. Es ist nicht einfach, den Datenabruf in den Controller zu starten. Mit einem Service verspotten Sie einfach den Service und Sie können den Controller mit stabilen, bekannten Daten testen.
  • Wartbarkeit. Sie können entscheiden, dass es sich bei einfachen Diensten um eine ähnliche Menge an Code handelt, um alles in den Controller zu legen, auch wenn Sie es wiederverwenden. Was passiert, wenn sich der Back-End-Pfad ändert? Jetzt müssen Sie es überall aktualisieren, wo es verwendet wird. Was passiert, wenn eine zusätzliche Logik zur Verarbeitung der Daten benötigt wird oder Sie zusätzliche Daten mit einem anderen Anruf erhalten müssen? Mit einem Service machen Sie den Wechsel an einem Ort. Mit den Controllern haben Sie mehr zu tun.
  • Code Klarheit. Sie möchten, dass Ihre Methoden klare, spezifische Dinge tun. Der Controller ist verantwortlich für die Logik um einen bestimmten Teil der Anwendung. Hinzufügen der Mechanik des Abrufs von Daten verwirrt das. Mit einem einfachen Beispiel ist die einzige zusätzliche Logik, die Sie benötigen, um den JSON zu dekodieren. Das ist nicht schlecht, wenn Ihr Backend genau die Daten zurückgibt, die Ihre Controller im genau richtigen Format benötigen, aber das ist möglicherweise nicht der Fall. Durch das Aufteilen des Codes kann jede Methode eine Sache gut machen. Lassen Sie den Service Daten erhalten und an den Controller im genau richtigen Format weitergeben, dann lassen Sie den Controller das machen.
0

Es würde Sinn machen, Ihren Dienst zu haben, wie folgt aussehen:

app.factory('AccountService', function($http) { 
    return { 
     getCurrentUser: function(param1, param2) { 
      var postOptions = {}; // build the postOptions based on params here 
      return $http.post("/Account/CurrentUser", {}, postOptions) 
      .then(function(response) { 
       // do some common processing here 
      }); 
     } 
    }; 
}); 

Dann Aufruf dieser Methode würde so aussehen:

$scope.getCurrentUser = function() { 
    AccountService.getCurrentUser(param1, param2) 
    .then(function(currentUser){ 
     // do your stuff here 
    }); 
}; 

die viel schöner aussieht und lässt Sie die Vermeidung von Wiederholungen von die Back-End-Service-URL und postOptions variable Konstruktion in mehreren Controllern.

+0

Ich muss zugeben, dass ich sehr unartig bin und "postOptions" als Variable auf Modulebene deklariere, also muss ich es nicht in jedem Controller konfigurieren. – ProfK

+0

Die andere Sache dabei ist, dass Ihr Controller nicht unbedingt derjenige ist, der den HTTP-Endpunkt aufruft. Wenn Sie den Aufruf an einen Dienst abstrahieren, können Sie ihn dann von anderen Diensten aufrufen lassen und seine eigene benutzerdefinierte Logik auf die Ergebnisse anwenden, bevor sie an den Controller zur Anzeige gelangen. –

2

Ein Controller führt die Präsentationslogik aus (er fungiert als Ansichtsmodell in der Ansicht "Angular Model-View-Whatever"). Dienste machen Geschäftslogik (Modell). Es ist eine in der Schlacht bewährte Trennung von Bedenken und inhärenter Bestandteil von OOP-Good Practices.

Thin Controller und Fat Services garantieren, dass App-Einheiten wiederverwendbar, testbar und wartbar bleiben.

Es gibt keinen Vorteil, $http durch RestService zu ersetzen, wenn sie das gleiche sind. Die richtige Trennung von Geschäfts- und Präsentationslogik wird erwartet, dass so etwas wie diese

$scope.getCurrentUser = function() { 
    return UserService.getCurrent() 
    .then(function(user) { 
    $scope.currentUser = user.id; 
    }) 
    .catch(function(err) { 
    alert("Browser failed to get current user."); 
    throw err; 
    }); 
}); 

Es kümmert sich um Ergebnis Anlage und gibt ein Versprechen zu sein. getCurrentUser besteht ein Versprechen, so könnte es bei Bedarf verkettet werden (durch andere Controller-Methode oder Test).

+0

Schöne Erinnerung an die Trennung von Sorgen, während ich festgefahren bin, so viel neues Zeug zu lernen. Ich bin in regelmäßigen C# -Apps religiös. – ProfK

0

Einfach. Schreiben Sie jede Funktion als Service, damit Sie sie wiederverwenden können. Da es sich um einen asynchronen Aufruf handelt, verwenden Sie eine Winkelverspre- chung, um die Daten zurück an den Controller zu senden, indem Sie sie innerhalb eines Versprechens einschließen.

Verwandte Themen