Moduli JavaScript e AngularJs Tecnica e struttura di implementazione

1

Quindi sto costruendo un'app e sto cercando di implementare la struttura dell'app in modo che sia robusta e scalabile in futuro.

La mia app è divisa principalmente in moduli JavaScript (pattern rivelatore) :

// filter.js file
//My javascript module structure
var filter = (function(){

var _privateMethod = function(){
}

var publicMethod = function(){
    _privateMethod();
}

return{
   publicMethod: publicMethod
}
});

Ora il problema principale è che voglio usare AngularJS anche all'interno della mia app e AngularJs ha i suoi moduli angolari in questo modo:

// app.js file
var myApp =  angular.module('myApp',[]);
myApp.controller('myController', function($scope){

});

Il modo in cui ho pianificato la mia app sviluppata è:

  1. Tutte le chiamate HTTP al server verranno eseguite all'interno del mio modulo JavaScript o per essere più chiare all'interno del mio "filter.js" file (vedi sopra)
  2. I dati restituiti dalle chiamate HTTP al server verranno quindi restituiti al controller angularjs o nel mio caso il "app.js" file (vedere sopra e il file controller / app.js sarà responsabile dell'aggiornamento del file view / html.

La ragione per fare questo è che tutte le mie funzioni che si collegano con il server e gestiscono i dati sono all'interno di un ambito privato (il modulo filter.js) e nessuno dovrebbe avere accesso a quelle funzioni in quanto vengono tenute fuori dal ambito globale.

Ma per passare i dati dal mio file filter.js al mio controller app.js angolare ho dovuto usare i callbacks

Di seguito è riportato il codice completo del mio scenario sopra descritto:

filter.js

var filter = (function(){

// public method
var testMethod = function(callback){
  loadDoc(function(dta){
    alert(dta);
    callback(dta);
 })
};

// private Method
function loadDoc(callback) {
  // Create the XHR object to do GET to /data resource  
  var xhr = new XMLHttpRequest();
  var dta;
  xhr.open("GET","url",true);

  // register the event handler
  xhr.addEventListener('load',function(){
  if(xhr.status === 200){
       //alert("We got data: " + xhr.response);
        dta = xhr.response;
        callback(dta);
   }
  },false) 

  // perform the work
  xhr.send();
  }

 return {
     testMethod: testMethod   
  };

})();

app.js:

var myApp = angular.module('myApp',[]);

myApp.controller('myController', function($scope){


$scope.myFunc = function(){

     filter.testMethod(function(dta){
        alert(dta);
        $scope.test = dta;
        console.log($scope.test);
      });
   };
});

Dalla mia precedente struttura di codice puoi vedere che sto utilizzando i callback per inviare dati ai miei controller.

La mia domanda:

  1. La mia domanda è che lo scenario sopra descritto di come vedo il mio codice implementazione e struttura, è quell'approccio giusto ?

  2. L'implementazione aderisce al javascript buono, pulito e corretto     codice?

  3. C'è qualcos'altro che posso fare per migliorare la struttura del codice della mia app?

posta Lorenzo von Matterhorn 26.01.2016 - 15:04
fonte

1 risposta

1

Direi che, nel caso di AngularJS, l'utilizzo di callback è un odore di codice. Dico questo per il semplice fatto che AngularJS include la nozione di promises che puoi sfruttare per lo stesso caso d'uso, e in effetti sembra molto simile nella pratica al codice che hai già sviluppato. Considera il tuo metodo di prova:

var testMethod = function() {
  return loadDoc();
};

function loadDoc(callback) {
    // Create the XHR object to do GET to /data resource  
    var xhr = new XMLHttpRequest();
    var dta, 
        // This is the deferred action
        defer = $q.defer(); 
    xhr.open("GET","url",true);

    // register the event handler
    xhr.addEventListener('load',function() {
        if(xhr.status === 200) {
            // We have a response, tell those who are waiting
            // about it
            defer.resolve(xhr.response);
        }

    }, false) ;

    // perform the work
    xhr.send();

    return defer.promise;
}

Il codice chiamante potrebbe essere simile a questo:

testMethod().then(function(data) {
    console.log('data', data);
});

Non solo, ma anche il codice chiamante potrebbe essere simile a questo:

function callTheTestMethod() {
    return testMethod().then(function(data) {
        console.log('data', data);

        return data;
    });
}

E il codice che chiama quel codice potrebbe apparire come questo:

callTheTestMethod().then(function(data) {
    console.log('I have data here, too', data);
});

Un altro vantaggio nell'usare le promesse è che hanno già un modo integrato per gestire i fallimenti:

if(xhr.status === 200) {
    defer.resolve(xhr.response);
} else if(xhr.status > 400 && xhr.status < 600) {
    defer.reject();
}

Basta dare uno sguardo al tuo codice, sembra che il tuo callback sia in realtà chiamato due volte , e per me sembra un bug. Inoltre, su una nota a margine, non penso che dovresti creare un'istanza della tua versione di XMLHttpRequest qui rispetto al solo utilizzo del servizio Angular $http , ma forse hai i tuoi motivi.

Suggerirei questo approccio: costruisci un servizio di AngularJS che utilizza il servizio di $http incorporato per sottrarre le tue chiamate API, qualcosa del genere:

angular.module('my.module', [])
    .service('TestService', [
        '$http',
        function($http) {
            return {
                testMethod: testMethod
            };

            function testMethod() {
                // Just a simple example to illustrate private 
                // method usage..
                var data = privateMethod();
                return $http.get('url/' + data);
            }

            // Since this function isn't returned in the object above, only
            // code that exists in this scope can actually reference it
            function privateMethod() {
                return '3';
            }
        }
    ])
;

Puoi utilizzare questo servizio in un controller (o in una direttiva o in un altro servizio) in questo modo:

angular.module('app.module', ['my.module'])
    .controller('TestController', [
        'TestService',
        function(TestService) {

            activate(); // Prepare for Angular 2.0!

            function activate() {
                TestService.testMethod().then(
                    function(data) {
                        console.log('I still have data', data);
                    },
                    function() {
                        console.log('something went wrong...');
                    }
                );
            }
        }
   ])
;
    
risposta data 26.01.2016 - 20:36
fonte