Which one to use in Angularjs : Factory, Service and Provider? - angularjs

Hi I am new with Angularjs. I am reading about Angular service. I have read the following
what-is-difference-between-factory-service-and-provider and service-vs-provider-vs-factory. To me, it seems like they are just different way of achieving same goal (please correct me if I am wrong.) Now I am wondering as they all serve the same purpose which one is idea to use and considered as best practice?

Sounds like the question is when to use which. First it's important to note that they are all providers. Each is a more specialized version of the other starting with provider. factory is a specialized version of provider. value and service in turn are specialized versions of factory.
And constant and value are specialized versions of each other. Because provider is at the top can therefore can do what all the other providers do you could get away using just providers. But you would be writing a lot of unnecessary code.
Each specialized provider down the chain, if you could use it would allow you to accomplish the same thing in less code. So you could say the best practice is to use the provider furthest down the chain that accomplishes what you wanted.
Here is a high level image showing you what I mean:
(source: simplygoodcode.com)
And below is the link to the blog post the image is from that gives you additional examples:
http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

There is no best practice, no one is going to tell you that one is better than the other (service vs factory).
Use a provider if you need to configure your service at run time (like you configure your router for example).
To when to use a factory or when to use a service, they are the same.
Factory has the easiest syntax to understand (using reveal module pattern) so that is the most common choice.
On the other hand, services are now more "useful" because they use the same syntax as the Angular 2 services, so if you plan in migrate someday, using services now will help the transition.

Related

Is it correct to access scope inside service or factory in angularjs

Disclaimer : I know there are certain questions which suggest not to access scope inside service or factory but here I am expecting the impact in terms of coding guidelines / whether it is advisable if not then I need proper justification.
We have angular js project and this project is old. Now after refactoring one of my colleague moved the common implementation from directive to service. While doing so , to access the scope of directive he manually started doing as below :
angular.element('<test-dir></test-dir>').scope();
What I felt is this is not the proper way to write the service/factory. I felt we are making the things complicated and suggested to remove the above part of code.
To justify the same I told :
1. This will make unit testability complicated and now we are trying to test the service the way we used to test directive.
2. And we are making this service tightly coupled with directive.
3. Service is not meant to access the scope.
But I think I am not able to convince him as I don't have much point to justify it. Can someone please suggest if I my understanding is correct and give proper justification to convice him. Thanks!
No, the services/factory are supposed to be working with data and should have the logic to process the data provided to them. Preferably, they should not refer to DOM objects or scope variables.
I personally believe that passing $scope to a service is a bad idea, because it creates a kinda circular reference: the controller depends on the service and the service depends on the scope of the controller.
On top of being confusing in terms of relations, things like this one end up getting in the way of the garbage collector.
A Service is just a function for the business layer of the application. It acts as a constructor function and is invoked once at runtime with new, much like you would with plain JavaScript (Angular is just calling a new instance under the hood for us).Use a service when you want to just create things that act as public APIs.
The service class should work on the data provided by the controller, making it reusable at any other place if needed. Also keeping the scope away from it, keeps the code lean and clean thus better maintainability.
I prefer to put a domain object in the controller scope and pass that to the service. This way the service works irrespective of it being used inside a controller or maybe inside another service in the future.

Organizing AngularJS applications

I feel like there is relatively little documentation on the "best practices" of how one should go about organizing AngularJS code. For example, in many of my web pages, i.e.
index.php
profile.php
editprofile.php
There are often many factories and methods that I need repeated. For example, profile.php,, editprofile.php, and index.php all need the factory userDropdown (to get the top navbar dropdown menu). However, some of them need "modified versions of factories". For example:
index.php needs a way to get all the users and their information
profile.php needs a way to get some users information
editProfile.php needs a way to get only one user information
What I mean is that (and the above was a poor example), is that often many .js files needs some modified "child" of a "parent" factory. I find it hard to scale my application because profile.php, index.php, and editProfile.php all refer to their own factories and methods, not a base file. Changes, improvements, errors, found in one factory and is corrected, will not propagate into other files (which I find very frustrating). I also don't want to write /copy/paste services and factories over and over again. Other issue I've had is that:
X.js file need some providers that Y.js file doesn't. However, both needs providers A and B, but X needs C and Y needs D. Is it bad for me to use the same "factory" and providers" for both of them (i.e. inject A, B, C, and D into both of them?) That's the problem I see with having a base factory of a factory to serve a lot of .js files. How much space or inefficiency is it to define providers or injectable services that you don't use?
How do I accomplish some scalable angularJS code to do this, or how do you guys go about organizing your angular code? And also, what about repeating HTML templates (i.e. repeating HTML code that needs to be used in almost every page? I've heard of some service called $templateCache but couldn't figure out how to use it.)
https://github.com/johnpapa/angular-styleguide This also has an example app but seriously read through his guidelines they seem to be exactly what you are looking for and have been a great resource for me as I've been learning to build bigger angular apps.

Good architecture MVC, API-calls

Me and some friends are currently doing a project where we are designing a webpage, where we do a number of api-calls using ajax.
We are using the Angular-framework, and we are wondering what is the correct architecture on where to put the API-calls. Right now we have them in our controllers, and saving the results as $scope-objects.
We are however wondering if it would actually be better praxis to have the API-calls in the model. We have been googling a lot, and can't seem to find an answer.
Encapsulating API calls in services is a good idea, but don't try to hide the fact that you are making web requests in your code. Have the services/model return descriptive promises and have your controller use the promises and handle errors gracefully. If using REST, you might want to use Angular's built in $resource factory. If the code is easy to unit test, it will be a sign that you're doing a good job. Being able to easily mock the services will make your controllers a lot easier to test.

pitfalls of IIFEs with AngularJS

I have an application made with angularJS, whole application is composed of IIFEs(Immediately Invoked Function Expression). Every module, directive, controller is itself an IIFE and they are around 100s.
I want to know what is the performance pitfall when an app has so many IIFEs.
It is OK to use IIFEs with AngularJS?
How good is using libs like browserify and requirejs with AngularJS for managing the dependencies?
Can you please throw some light on this?
The question you need to ask first is whether you've got some internal parts within the IIFE that you don't want to expose to the global scope.
The whole point of creating a closure in this manner is to mimic encapsulation and avoid polluting the global scope.
The performance pitfall is not so easy to measure; I think the performance issue is negligible when you create the IIFE (don't forget you're just creating a function). One performance issue that I might think of is that when you reference a function variable form an inner function, you need to travel through the scope chain and get it from the closure object.
I would recommend you to look at patterns like module pattern, revealing module pattern etc. I personally use the revealing module pattern.
Browserify and requireJS are two libraries that implement two different specs; the commonJS and AMD respectively. These two specifications try to accommodate a functionality that is not supported by ES3 or ES5; That is a way of defining module and then loading them in specified locations.
If you want to define modules and load them synchronously in a similar manner to hose nodeJS works, you can use Browserify. In addition, Browserify allows you to use the same modules both for client-side and server-side (as long as you're using nodeJS).
On the other hand if you want to asynchronously load your modules you can go with AMD and requireJS, but you won't be able to reuse them on the back-end.
Finally, bare in mind that everything you've mentioned is not directly connected to angularJS; those are some good JavaScript practises to overcome some issues of the language itself. It can be well used whether you're working with angular or not.
I would recommend that you use either browserify or requireJS; it will benefit you in the long run. Just imagine having 100 JS files; you would need to out the manually into your html in the correct order based on the dependency graph. You can easily come across issues like race conditions where one file should have been inserted before another one.
As for the performance overhead of IIFEs, you shouldn't have any serious issues.
As another answer said, IIFEs are a good general practice, independent of AngularJS.
If you're concerned about the performance of IIFEs, go ahead and check out these performance tests on JSPerf (or write your own):
http://jsperf.com/iife-antecedents-in-js
http://jsperf.com/immediate-anonymous-function-invocation
While some ways of IIFE creation are clearly much slower than others, I wouldn't worry about the performance of IIFEs unless you're in a large loop.

What is the correct way to solve the ambiguous reference issue in WCF services?

Project Structure
I have a silverlight project SLProj, that references a silverlight class library project called ServiceClients. ServiceClients has two wcf service references, Svc1.svc and Svc2.svc. Both Svc1.svc and Svc2.svc are in two different WCF projects which use the same set of DataContracts which are again in a different class library project called MyDataContracts.dll.
Problem description
Now in my ServiceClients project I get an ambiguous reference issue when I need to use a datacontract class which is present in both the service references. If this were a winforms or webforms project, I could reference the MyDataContracts.dll and reuse the common types. But since, this MyDataContracts.dll was built using a non silverlight class library, it can't be referenced in the silverlight project
Workaround...
I am not sure if this below is the best method to go about taking care of this issue. Can anybody let me know if there is a cleaner way to solve this problem, or is this the best way we have so far?
create a single service reference.
click the 'show all files' button in the solution explorer
drill into the service reference and find Reference.svcmap and open it
find the MetadataSources section
add a second line to include the address to your second service. for example:
MetadataSource Address="http://address1.svc" Protocol="http" SourceId="1"
MetadataSource Address="http://address2.svc" Protocol="http" SourceId="2"
save, close, and update service reference.
Use Automapper
Map the DataContracts with AutoMapper.
You will have to invest some time in understanding AutoMapper and reworking your application. Also AutoMapper adds overhead because all data objects will be mapped. But first you will have a clean solution without hacks and second you gain a decoupled and simple data object layer just for your client. Once done you can forget the mapping but you stay flexible for future changes.
If you never have worked with Automapper it's important to play around with it before starting. Automapper is special and needs some time to familiarise with it.
So there. These are the rough steps:
1. Create a subdirectory and sub-namespace Data and copy the DataContracts. Remove the attributes and properties your client doesn't need because these mapped classes live only in your client. You can also change some types or flatten some complex properties.
2. Create an AutoMapperInit.cs like described at Automapper (read the Getting Started Guide). Use the conflicting references like this:
using ref1 = YourProjectServiceReference1;
using ref2 = YourProjectServiceReference2;
3. Wrap the service client like this:
Example GetExample() {
return AutoMapper.Map<ref1.Example, Example>(ref1.YourService.GetExample());
}
The wrapper also needs the same using directives as in step 2.
4. In this wrapper add a static initializer like this (assuming your wrapper class is called Wrapper):
static Wrapper() {
AutoMapperInit.CreateMaps();
}
5. Omit service references in the client and use using YourClient.Data;, the namespace you created in step 1.
Your client is now decoupled from the service and you don't have conflicts anymore.
Disclaimer: I am not affiliated with AutoMapper. I just used it in a project with a similar problem and am happy with it and wanted to share my experience.
Your workaround is actually quite OK. We've used it in several projects like this with 3 service references. It is actually a workaround for the IDE which for some reason only allows to select one service to create a service reference at a time.
Another thing you could try-out is to multi-target your shared contract to .NET and Silverlight, using the same codebase. Details on how to do such thing is described in http://10rem.net/blog/2009/07/13/sharing-entities-between-wcf-and-silverlight. Might be more work but feel less hacky.

Resources