Factory methods in multiple files Angular JS
Asked Answered
C

3

6

What is the best practice when you have a Factory with like 4 related methods, each of those is really long (200+ lines of code) and you want to avoid having a huge file of 800+ lines of code?

One solution is to create 4 factories under the same module , each one exposing a single method and in its own file. Then inject all of them in the controller that requires them.

Is there a better solution? I'd like to create the Factory once, then add methods to it like I was doing module augmentation using the module pattern. Then I just need to inject the Factory once and have all its methods available.

Clarence answered 16/9, 2014 at 12:16 Comment(6)
Why are your methods 200+ lines of code? Sounds like a refactor is the best solution. Possibly post one of these giant methods for code review.Sami
Unfortunately I cannot shrink them anymore than that, not all of them though, but I see your point. I have a bunch of try/catch and if/else to go through due to the application logic.Clarence
If it isn't sensitive code, would you be able to post an example of one of your huge methods somewhere? Purely out of curiosity, I would like to see one.Sami
I quickly pasted one here jsfiddle.net/mirko77/82ksvuLa, the only thing I see is placing the success/error callbacks in different files, but should I?Clarence
Much of that file can be refactored into smaller, more useful functions, and could also be made much more concise and simple.Sami
I do agree, I was looking for a general solution about how to split Factories the same way we can split modules.Clarence
R
1

You could also arrange your code the old vanilla js style and then access those libraries in your services like this:

var Mirko = { };

Mirko.FunService = {
  getAllSomething : function (p1, p2) {
  },
  ...
};

angular.module('myModule').factory('BigService', function(){
  return {
    methodOne : Mirko.getAllSomething,
    ...
  };
});

You will end up with one object Mirko that you can access outside the scope of your angular app, but it will in no way differ from other externals api's (not written for angular) you would want to use in your app. The way you handle your own 'external' api can be done the oldschool fashion way, one file per 'class' e.g. 'FunService'.

It might not be the prettiest solution but it will be an easy abstraction.

Just saying...

Reggiereggis answered 16/9, 2014 at 12:32 Comment(3)
Thanks. That would be exactly the scenario I am trying to port to Angular ;) I have an existing app built using the module pattern where my objects are namespaced under a main APP object, then APP.Module1 ={}, APP.Module2{} and so on. I thought Angular had a way to handle this, am I the only one having long methods? (if 200 lines with comments can be called "long")Clarence
Well i upvoted your question because i wanted to know if there was a better alternative than the one i propose - so now i guess we're playing the waiting game :)Fagot
For the time being this is still the best solution and I will accept it. Let's wait!Clarence
G
3

I'd like to create the Factory once, then add methods to it like I was doing module augmentation using the module pattern. Then I just need to inject the Factory once and have all its methods available.

Yes, that will work:

// In your main module file.
angular.module('myModule', []);


// file1.js
angular.module('myModule').factory('BigService1', function(){
    // Your actual implementation here.
    console.log('I am BigService1');
});


// file2.js
angular.module('myModule').factory('BigService2', function(){
    // Your actual implementation here.
    console.log('I am BigService2');
});


// ... additional files


// Separate file/service to aggregate your big factory services.
angular.module('myModule').service('AggregateService', [
        // Add dependencies
        'BigService1','BigService2',
function(BigService1, BigService2){
    // Return an object that exposes the factory interfaces.
    return {
        service1: BigService1,
        service2: BigService2
    };
}]);
Gisellegish answered 16/9, 2014 at 12:27 Comment(0)
R
1

You could also arrange your code the old vanilla js style and then access those libraries in your services like this:

var Mirko = { };

Mirko.FunService = {
  getAllSomething : function (p1, p2) {
  },
  ...
};

angular.module('myModule').factory('BigService', function(){
  return {
    methodOne : Mirko.getAllSomething,
    ...
  };
});

You will end up with one object Mirko that you can access outside the scope of your angular app, but it will in no way differ from other externals api's (not written for angular) you would want to use in your app. The way you handle your own 'external' api can be done the oldschool fashion way, one file per 'class' e.g. 'FunService'.

It might not be the prettiest solution but it will be an easy abstraction.

Just saying...

Reggiereggis answered 16/9, 2014 at 12:32 Comment(3)
Thanks. That would be exactly the scenario I am trying to port to Angular ;) I have an existing app built using the module pattern where my objects are namespaced under a main APP object, then APP.Module1 ={}, APP.Module2{} and so on. I thought Angular had a way to handle this, am I the only one having long methods? (if 200 lines with comments can be called "long")Clarence
Well i upvoted your question because i wanted to know if there was a better alternative than the one i propose - so now i guess we're playing the waiting game :)Fagot
For the time being this is still the best solution and I will accept it. Let's wait!Clarence
D
0

Maybe segment your methods through other factories, which can be injected to your "main" factory :

// file 1
angular.module('foo').factory('segment1', function () {
  return {
    method: function () {
      // ... super long method
    }
  };
});

// file 2
angular.module('foo').factory('segment2', function () {
  return {
    method: function () {
      // ... super long method
    }
  };
});

// your main factory file
angular.module('foo').factory('myFactory', function (segment1, segment2) {
  return {
    method1: segment1.method,
    method2: segment2.method
  };
}
Danger answered 16/9, 2014 at 12:27 Comment(5)
Ah, you beat me to it :)Gisellegish
Only one gripe though, this will still require me to create 4 factories, plus one to aggregate them. Is there a chance to retrieve an existing factory and inject a method to it?Clarence
I dont think so, sadly.. It will 'erase' precedently defined factory.Danger
the @Per Hornshøj-Schierbeck solution would be a better one for this purpose, so.Danger
I agree, @Per Hornshøj-Schierbeck solution is better for this purposeClarence

© 2022 - 2024 — McMap. All rights reserved.