1

So Im building an app and I'm trying to implement the structure of the app so that its robust and scalable in future.

My app is mostly divided into JavaScript Modules (revealing pattern):

// filter.js file //My javascript module structure var filter = (function(){ var _privateMethod = function(){ } var publicMethod = function(){ _privateMethod(); } return{ publicMethod: publicMethod } }); 

Now the main issue is that I want to use AngularJS within my app too and AngularJs has its own angular modules like so:

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

The way I have planned my app developed is:

  1. All HTTP calls to the server will be done within my JavaScript module or to be more clear within my "filter.js" file (see above)
  2. Returned data from the HTTP calls to server will then be sent back to angularjs controller or in my case the "app.js" file (see above) and that controller/app.js file will be responsible for updating my view/html file.

The reason for doing this is so that all my functions that connect with server and handle data are within a private scope (the filter.js module) and no one should have access to those functions as they are being kept out of the global scope.

But to pass data from my filter.js file to my Angular app.js controller I had to use callbacks.

Below is the complete code of my above described scenario:

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

You can see from my above code structure that I am using callbacks to send data back to my controllers.

My Question:

  1. My question is that the above descried scenario of how I see my code implementation and structure, is that right approach?

  2. Does the implementation adhere to good, clean and correct javascript code?

  3. Is there something else I can do to improve my app's code structure?

    1 Answer 1

    1

    I would argue that, in the case of AngularJS, utilizing callbacks is a code smell. I say this for the pure simple fact that AngularJS includes the notion of promises that you can leverage for the same use-case, and in fact look extremely similar in practice to the code you have already developed. Consider your test method:

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

    The calling code could look like this:

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

    Not only that, but the calling code could also look like this:

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

    And the code calling that code could look like this:

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

    Another benefit to using promises is that they already have a built-in way to handle failures:

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

    Just glancing at your code, it looks like your callback is actually being called twice, and to me looks like a bug. Also, on a side note, I don't think you should be instantiating your own version of XMLHttpRequest here vs just using the Angular $http service, but perhaps you have your reasons.

    I would suggest this approach: Build an AngularJS service that uses the built in $http service to abstract away your API Calls, something like this:

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

    You can consume this service in a controller (or directive, or another service) in this fashion:

    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...'); } ); } } ]) ; 
    5
    • Thank you so much for the answer.What I understand from this ( and correct me if Im wrong ) that using callbacks in AngularJs is not a good practice and instead Promises should be used instead of call backs when using AngularJs, is this correct? The 2nd thing that I would really like to get a clarification on is the use JavaScript Modules (revealing pattern) with AngularJs Modules. Do you think that concept or logic is justified. Or should I completely remove the JavaScript Modules and handle all calls to the API/Server from my AngularJs using the built in $http service. Again Thank you!CommentedJan 26, 2016 at 20:11
    • Just to clarify, the reason I am trying to use JavaScript Module Pattern is to provide privacy to functions hence making my app more secure. Also this way I can separate all the major functions of my app into modules and that would make scaling and debugging the app in future much much easier.CommentedJan 26, 2016 at 20:14
    • AngularJS already includes the notion of modules, and I've shown you above how you can make one depend on the other (just focus on the first line of the last snippet). If the only thing your public method does is call your private method, then your private method is not private because it's been aliased by the public one.CommentedJan 26, 2016 at 20:19
    • @LorenzovonMatterhorn FYI- I took another look and updated the example I used to give you a sense of how you can utilize a private method within your service. Nothing outside of the TestService will be able to reference privateMethod in order to call it. Because of how it's defined and JavaScript's scope hoisting, any other function defined in the service will be able to reference it.CommentedJan 27, 2016 at 0:35
    • @LorenzovonMatterhorn Generally speaking, using callbacks is fine in Angular. Promises don't make sense everywhere. But this case is definitely a situation where promises apply, and you don't really have a choice if you use the $http service. And you should definitely use the $http service to make Ajax calls.
      – Mohair
      CommentedJan 27, 2016 at 3:13

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.