2016-06-04 18 views
7

Attualmente ho chiamate come questo tutto il mio tre 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."); 
      }); 
}; 

Vedo un sacco di consigli per incapsulare le $http chiamate in un HTTPService, o qualcosa del genere, ma che è molto meglio la pratica di restituire la promessa di restituire i dati. Eppure, se torno la promessa, tutti, ma una linea nel mio controller $http cambiamenti di chiamata, e tutta la logica di trattare con la risposta rimane nella mia controller, ad esempio:

$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."); 
      }); 
}; 

ho potuto creare un RestService per ciascun lato server controller, ma questo finirebbe solo per chiamare un servizio di base e passare l'URL comunque.

+1

possibile duplicato http://stackoverflow.com/questions/17646034/what-is-the-best-practice-for-making-an-ajax-call-in-angular-js~~V~~singular~~3rd – jbe

+0

vantaggi dei servizi: il codice di facile riutilizzo , facile controllo e test di servizio, facile servizio di simulazione. – dfsq

risposta

2

Ci sono alcuni motivi per cui è una buona pratica in applicazioni non banali.

L'utilizzo di un singolo servizio generico e il passaggio dell'URL e dei parametri non aggiungono così tanto valore come notato. Invece avresti un metodo per ogni tipo di recupero che devi fare.

Alcuni vantaggi dell'utilizzo di servizi:

  • riutilizzabilità. In una semplice app, potrebbe esserci un recupero dati per ogni controller. Ma questo può presto cambiare. Ad esempio, potresti avere una pagina di elenco dei prodotti con getProducts e una pagina di dettaglio con getProductDetail. Ma poi vuoi aggiungere una pagina di vendita, una pagina di categoria o mostrare i prodotti correlati nella pagina dei dettagli. Questi potrebbero tutti utilizzare i getProducts originali (con parametri appropriati).
  • Test. Si desidera essere in grado di testare il controller, separatamente da un'origine dati esterna. Cucinare i dati sul controller non è così facile. Con un servizio, si prende in giro il servizio e si può testare il controller con dati stabili e noti.
  • Manutenibilità. Potresti decidere che con servizi semplici, è una quantità simile di codice per mettere tutto nel controller, anche se lo stai riutilizzando. Cosa succede se il percorso back-end cambia? Ora devi aggiornarlo ovunque sia usato. Cosa succede se è necessaria una logica aggiuntiva per elaborare i dati o è necessario ottenere alcuni dati supplementari con un'altra chiamata? Con un servizio, apporti la modifica in un unico posto. Con esso cotta nei controller, hai più lavoro da fare.
  • Chiarezza codice. Vuoi che i tuoi metodi facciano cose chiare e specifiche. Il controller è responsabile della logica attorno a una parte specifica dell'applicazione. Aggiungendo la meccanica del recupero dei dati confondilo. Con un semplice esempio l'unica logica aggiuntiva di cui hai bisogno è decodificare il json. Non è male se il tuo back-end restituisce esattamente i dati necessari ai tuoi controller nel formato esatto, ma potrebbe non essere il caso. Suddividendo il codice, ogni metodo può fare bene una cosa. Lascia che il servizio ottenga i dati e li trasmetta al controller nel formato esatto, quindi lascia che sia il controller a farlo.
0

In questo senso sarebbe di avere il vostro servizio simile a questa:

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 
      }); 
     } 
    }; 
}); 

Poi la chiamata a questo metodo sarebbe guardare in questo modo:

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

che sembra molto più bello e consente di evitare la ripetizione di l'URL del servizio di backend e la costruzione della variabile postOptions in più controller.

+0

Devo ammettere di essere molto cattivo e dichiarare 'postOptions' come una variabile di livello del modulo, quindi non devo configurarlo in ogni controller. – ProfK

+0

L'altra cosa nel farlo in questo modo, è che il mio controller non è necessariamente quello che chiama l'endpoint http. Effettuando l'astrazione della chiamata a un servizio, è possibile quindi chiamare altri servizi e applicare la propria logica personalizzata ai risultati, molto prima che venga visualizzato sul controller. –

2

Un controller esegue la logica di presentazione (si comporta come un modello di vista nel modello Modello angolare-Vista-Qualunque). I servizi fanno la logica aziendale (modello). È una separazione collaudata delle preoccupazioni e parte intrinseca delle buone pratiche OOP.

I thin controller e il fat service garantiscono che le unità dell'app rimangano riutilizzabili, testabili e manutenibili.

Non c'è alcun vantaggio nella sostituzione di $http con RestService se sono la stessa cosa. La corretta separazione della logica di business e presentazione dovrebbe essere qualcosa di simile

$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; 
    }); 
}); 

Si prende cura di risultato condizionata e restituisce una promessa. getCurrentUser passa una promessa, quindi potrebbe essere incatenato se necessario (con altri metodi o test del controller).

+0

Bel ricordo della separazione delle preoccupazioni mentre sono impantanato a imparare tante cose nuove. Sono religioso a riguardo nelle normali app C#. – ProfK

0

Semplice. Scrivi ogni funzione come servizio in modo da poterla riutilizzare. Poiché si tratta di una chiamata asincrona, utilizzare la promessa angolare di inviare i dati al controller avvolgendolo in una promessa.

Problemi correlati