AngularJS - Migrating jQuery functions to angular ones - angularjs

I am taking over a big (50+ modules) AngularJS project, from another programmer, which did not do it right, so I have several migration questions:
There are lots of usages of JS functions like setTimeout and setInterval. It will be very easy to change to $timeout and $interval (because they use the same syntax, so it is just find and replace), but should I bother?
The entire project is without services, and all data requests run in the controllerss. Should I make time to create services for all controllers, the most important ones, or none? (I know that "if it works dont fix it", but from your experience does this make your life easier?)
The ENTIRE project uses $.ajax, with over a thousand requests. I do not have the time to migrate all requests to use $http, but I will try over time. In the meanwhile, should I create a service like $http_o and replace all "$.ajax(" strings in all files to $http_o, so the service will pretty much get a normal ajax request syntax, and send it using the $http service.
Every controller's services are written in a variable name, and not with a string at the start (function($scope) instead of ['$scope', function($scope)). Is there a fast way to change all of them to use the normal syntax, so I can use a minifier, or do I have to do it by hand? Should I do it?
I will obviously try my best to rework modules to use correct MVC and angular rules in my spare time at work, but this will happen way ahead in the future.

It's not as trivial as you might think i.e. $interval applies a $rootScope.$apply() at end so it will trigger $digest cycle, with lots of intervals it might slow down app
It's all about readability and maintainability. I'd say yes, do separate services and DRY the application otherwise when you will have to debug it in 3 months time it's going to be hell
A smart regex could work for you although the advantage of using $http over $.ajax is that you don't have to use tricks to trigger change in view - i.e. manually run $digest or $apply
You can do it easily with https://github.com/olov/ng-annotate

Related

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.

Dynamically override angular service?

Use case:
I'm writing system tests using Geb/Selenium (so outside of angular).
I want to decorate $http to log all requests/responses at run time.
and here's the catch: without touching the source code.
Before you rush to answer "use $provide#decorator", for example,
http://blog.xebia.com/2014/08/08/extending-angularjs-services-with-the-decorate-method/
That solution for this use case means adding a test hook into production code... that's normally a bad thing I want to avoid if possible.
Update: Geb allows you to run Javascript in the browser window. So just for the heck of it I ran the tutorial code to decorate $http. Unfortunately, it didn't work because apparently you can't re-config the app after it's been loaded. But even if it did work, this brings up another interesting point---I need to override $http before any modules have had a chance to use it.
Since decorating $http service would be the cleanest way of doing this, you can avoid polluting production code by using something like ng-constants and gulp/grunt to only add decoration code for a 'test' environment.
See related Q/A here: How do I configure different environments in Angular.js?
If you are inclined on changing this at runtime(where runtime takes place in a test environment), you may need to go 'closer to the metal' and deal with XMLHttpRequests: Add a "hook" to all AJAX requests on a page

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.

Testing a controller in Angular with several dependencies

I am learning to write unit tests for my angular app. My controller has several dependencies upon Resources, factories, services etc
angular.module('app').controller('Ctrl1',['$scope','Factory1','Factory2','Resource1','Resource2' ... and so on
The Resource1, Resource2, etc of course fetch data from the server. Several of these resources are used to fetch data from the server and initialize $scope.
After reading innumerous tutorials all over the net, I have a few queries on the right way to write my jasmine tests
In the beforeEach section of the jasmine test, am I suppose to provide all dependencies right away or should I provide only the ones I care about testing
What I want to test is that Resource1 gets called and fetches some data and intializes some part of $scope then Resource2 gets called and fetches some data and initializes some other part of scope etc
What is the right way to perform the above. I mean am I actually suppose to fetch the data in the test or should I be using some mock http service. I know tutorials mention that we should use mock http service but then how will this test my controller since I am not actually fetching the right data.
This part is really confusing and I have yet to find a blog/article that explains this clearly (I might just write one once I figure things out.. I am sure others are confused too)
Where to Provide Dependencies
You should provide all of your dependencies in your first beforeEach statement. I mock/fake mine with SinonJs. This helps you take advantage of angular's dependency injection to isolate each piece of your application. You should never call a dependency and expect an actual instance of it to return data in a unit test, as that would increase the coupling of your code and make it far more brittle.
Mocking Resource Calls
For resource calls, I simply create a fake resource object with promises and whatnot included. You can then resolve or reject those promises and provide fake data to test your controller logic.
In the plunk below, I've essentially mocked out a whole promise chain. You simply tell your tests to either reject or resolve those promises, faking a successful or failure call to the resource. You then have to make sure your scope cycles with scope.$apply(). I actually forgot to do this which caused me quite a bit of trouble just now.
Conclusion
Here is the Plunk. Let me know if you need to see how I test the actual resource code in my repositories. In those services I have to actually mock out the HTTP calls, which Angular makes extremely easy.
I'm not sure any of this is "Best Practice" but it has worked for me. I learned the basics from looking at other people's source code and watching this Pluralsite video AngularJS Fundamentals which has a very small section on testing.
Useful Resources
Testing AngularJS Directives. This is the hardest thing to test and understand in Angular. Or at least it was for me.
This one is on Dependency Injection in Angular. I have it marked
about where they start talking about unit testing.
This Plural Sight Course got me started with testing JavaScript in general. Very helpful for learning Jasmine if you are new to it.
AngularJS Github repo is very useful if you want to see Jasmine tests in action. Here is a set of tests that simulates a HTTP Backend.

Purpose of AngularJS Services

I'm new to AngularJS. I'm currently looking at the services. Some of these services look like the replace functions already available in JavaScript. For instance, the $timeout service. Why does AngularJS have these services? Is there a technical reason? Are there any advantages to this approach? I just don't understand the need for using these services.
Thank you for any help.
A service is a function or an object, with a set of methods, that could be used by several components (controllers, directives, filters, other services) of your application.
The main advantage that "wrapping" services like $timeout or $window have over their global functions equivalent is that they're injected by Angular, and can thus be mocked in unit tests, i.e. replaced by fake implementations.
Read the chapter about dependency injection in the angular documentation. Regarding the $timeout service in particular, its documentation explains what it does in addition to the native setTimeout() function.
Angular uses dirty check -- it keeps track of all variables that should be updated automatically and in case of any changes iterates through them as many times as needed (as there can be interdependence between observing variables). (To be precise if there are too many iterations something wrong is probably with your code and exception is raised).
The main reason behind $timeout is to signal to Angular engine that you will be making some changes to the observing variables in the callback. In case you would call normal timeout there is a way to inform Angular about those changes by calling e.g. $scope.$apply(function() {...}).
The other big reason, as #JB Nizet stated is that mocking is much easier.
Service is a way to store persistent information over your application.
unlike the $scope, which is an new child of $rootScope per each route\controller.
The purpose of the Angular-specific implementation of already existent functions, is to make your life and work easier, by automatically telling angular to register your changes, and apply them to the current scope at the next $digest iteration.
I'll be happy to address any other questions.
Good luck with Angular! :)
I will now create an example plunk to emphasize the idea to you
UPDATE:
This is the plunker:
http://plnkr.co/edit/mVmhZpEdsZDQ0MUQpFJ7?p=preview
I used ng-change and the native change
keyup event to explain the point.
while using the angular built in ng-change directive requires no additional effort nor code, using the native events requires wrapping everything in the scope.$apply function/
calling scope.$digest manually.
(run the code and see for yourself)
Check out this older answer which covers Services, Providers and Factories.
AngularJS: Service vs provider vs factory

Resources