I have a get request in angular that returns a streaming response. The request is made through the oboe library. The streaming response basically returns json values and my angular front end adds each of these streams to the scope on receiving each json object. Since oboe is not a part of angular itself, I am using $scope.$digest to update my scope. This is cause a huge memory leak for larger requests. I have figured that I have to use $destroy at some point. Can someone please tell me on which event I should use the $destroy for optimal performance?
I would have to think a little more about the angular internals to give a good answer. However, have you considered using https://github.com/RonB/angular-oboe, or talking a look at how that project deals with updates? They don't seem to use either $digest or $destoy
Related
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.
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
I'm struggling dealing with Protractor's asynchronous nature.
On different connections or browsers, it seems that elements are sometimes found, sometimes not, depending on my connection speed.
Short of using .then() callbacks, what options are available to me within Protractor to deal with it's Async issues to make sure elements are fully loaded before moving onto the next action?
Thanks!
I had many problems like that.. to resolve it, if a element depends of a asynchronous call to be showed, I always put a browser wait before.
browser.wait(protractor.ExpectedConditions.elementToBeClickable(element(by.id('elementId'))), 3000);
element(by.id('elementId').click()
Based on your other question, it would seem you're testing a non-angular application. Hence, you will want to use ignoreSynchronization.
And thus, you'll need to handle async and all it's quirks yourself. Eg. using then() callbacks, and ExpectedConditions and the like.
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
All,
We are developing our app with AngularJS and time and again we keep running into the issue of Angular running or loading controllers twice. This becomes a little more intrusive when testing our controllers and more specifically when working with Testacular with jasmine's SpyOn's (since they get triggered before our code runs). So, our question is, is there such a thing as a constructor or init method that Angular is guaranteed to call when instantiating the controllers w/o having to hack work-arounds in the test code? TIA.
If you are specifying the controller in your router, then your template doesn't need to specify the controller via an ng-controller tag. Doing so will double load your controller.
Your controllers shouldn't be loaded twice, unless you are doing something wrong. You shouldn't have to hack any work-arounds.
You might want to provide a concrete example of how you are loading the controllers (and/or the partials which are associated with the controllers). It sounds like you probably have a routing issue which is causing your view to be loaded twice for each request.
Assuming that is a routing-related issue, unless/until you can provide more information to help people to help you, you may want to read this document. Pay particular mention to sections that mention 'redirect' and 'HTML 5' mode:
http://docs.angularjs.org/guide/dev_guide.services.$location
With so little information to go on, I can't answer your question, but perhaps that link will help you to help yourself. :)