Angular English Flashcards
List at least three ways to communicate between modules of your application using core AngularJS functionality.
Common ways to communicate between modules of your application using core AngularJS functionality include:
Using services Using events By assigning models on $rootScope Directly between controllers, using $parent, \$\$childHead, \$\$nextSibling, etc. Directly between controllers, using ControllerAs, or other forms of inheritance
Which means of communication between modules of your application are easily testable?
Using a service is definitely easy to test. Services are injected, and in a test either a real service can be used or it can be mocked.
Events can be tested. In unit testing controllers, they usually are instantiated. For testing events on $rootScope, it must be injected into the test.
Testing $rootScope against the existence of some arbitrary models is testable, but sharing data through $rootScope is not considered a good practice.
For testing direct communication between controllers, the expected results should probably be mocked. Otherwise, controllers would need to be manually instantiated to have the right context.
When a scope is terminated, two similar “destroy” events are fired. What are they used for, and why are there two?
The first one is an AngularJS event, “$destroy”, and the second one is a jqLite / jQuery event “$destroy”. The first one can be used by AngularJS scopes where they are accessible, such as in controllers or link functions.
How do you reset a “$timeout”, and disable a “$watch()”?
The key to both is assigning the result of the function to a variable.
To cleanup the timeout, just “.cancel()” it:
var customTimeout = $timeout(function () { // arbitrary code }, 55);
$timeout.cancel(customTimeout);
Name and describe the phases of a directive definition function execution, or describe how directives are instantiated.
The flow is as follows:
First, the “$compile()” function is executed which returns two link functions, preLink and postLink. That function is executed for every directive, starting from parent, then child, then grandchild.
Secondly, two functions are executed for every directive: the controller and the prelink function. The order of execution again starts with the parent element, then child, then grandchild, etc.
The last function postLink is executed in the inverse order. That is, it is first executed for grandchild, then child, then parent.
How does interpolation, e.g. “{{ someModel }}”, actually work?
It relies on $interpolation, a service which is called by the compiler. It evaluates text and markup which may contain AngularJS expressions. For every interpolated expression, a “watch()” is set. $interpolation returns a function, which has a single argument, “context”. By calling that function and providing a scope as context, the expressions are “$parse()”d against that scope.
How does the digest phase work?
In a nutshell, on every digest cycle all scope models are compared against their previous values. That is dirty checking. If change is detected, the watches set on that model are fired. Then another digest cycle executes, and so on until all models are stable.
It is probably important to mention that there is no “.$digest()” polling. That means that every time it is being called deliberately. As long as core directives are used, we don’t need to worry, but when external code changes models the digest cycle needs to be called manually. Usually to do that, “.$apply()” or similar is used, and not “.$digest()” directly.
List a few ways to improve performance in an AngularJS app.
The two officially recommended methods for production are disabling debug data and enabling strict DI mode.
The first one can be enabled through the $compileProvider:
myApp.config(function ($compileProvider) {
$compileProvider.debugInfoEnabled(false);
});
Using one-time binding where possible. Those bindings are set, e.g. in “{{ ::someModel }}” interpolations by prefixing the model with two colons. In such a case, no watch is set and the model is ignored during digest.
What is $rootScope and how does it relate to $scope?
$rootScope is the parent object of all $scope Angular objects created in a web page.
What exactly are controllers? What is their lifecycle and relation to the scope?
Controllers are classes, that is, constructor functions, which are bound to a scope AND a section of HTML through the directive “ng-controller”, routing, or through a directive. Setting a controller creates a new scope (child scope). The controller’s purpose is to set up the initial state of the scope and also manipulate it by adding behaviour, setting watches, event listeners, etc.
Please explain what “.$eval()” and “$parse()” are used for in AngularJS.
“.$eval()” is a simple scope method which takes an expression (and optionally locals) and then executes it against the current scope, using “$parse()”.
The service “$parse()” is where the magic happens. It takes an Angular expression and returns a function, which takes two arguments: “context” and “locals”. The latter is used for overriding variables set in the context. The context is the key part.
What is the difference between “.$apply()” and “.$applyAsync()”? Why would you choose one over the other?
The main difference between them is that the latter happens on a 0 timeout. The actual delay is about 10ms. Consecutive “.$applyAsync()” calls cancel the previous timeouts. The point is that for multiple “.$applyAsync()” calls, there will only be a single digest trigger, and not one for every call. That would be the case with the regular “.$apply()”.
What is the difference between “.$digest()” and “.$apply()”? Why would you ever call “.$digest()” on a scope?
There are a few differences. First of all, “.$apply()” takes an argument, an expression, and evaluates it against the current scope. “.$digest()” does not take any arguments.
Secondly, “.$apply()” calls “.$digest()” on root scope. That digest will propagate down through every child scope — it will eventually affect every scope in the application. Calling “.$digest()” directly on a scope does not affect any scope that is higher in the hierarchy. That means that any watches set on parent scopes will not be evaluated.
Please explain when to use a service, when to use a factory, and when to use a provider.
The three are almost the same internally. When initialized, a service returns a factory, which in turn returns a provider.
The difference between services and factories lies in how they are declared and initialized. Services are constructor functions — they are instantiated, that is, when first loaded a “new” instance is created. The consequence is that when declaring a service, all its methods are defined as properties of “this”. Factories, on the other hand, should return an object literal.
There is an advantage to knowingly using providers, as they can be configured before all services are available, in “config()” blocks. When declaring a provider named e.g. “api”, Angular registers two injectables: “api” and “apiProvider”.
What are services in AngularJS? When are they initialized?
Angular services are singletons — there is only one instance available during an app’s lifecycle. Angular lazy loads its modules, so all services become available after they were injected into a “run()” block, or into another module (which of course needs to be initialized too).
What means of HTTP communication are available in AngularJS? Describe and explain the differences between at least two.
The two core services for Angular that deal with XHRs are “$http” and “$resource”. The latter actually needs explicit installation, while “$http” is readily available.
“$http” is a low level module, which already provides a lot of functionality, but using it with a RESTful API might lead to duplication of code, and is somewhat primitive. The module can be used for communicating using XML HTTP Requests or JSONP. It is rather simple to use.
“$resource”, on the other hand, is a high level service built on top of “$http”, designed for communicating with RESTful APIs. It was built to deal with standard server-side resources. It provides a rich api, allowing the declaration and reuse of multiple defined parameters, even ones which can be used alternatively on the same path level. It provides standard actions (except for “update”, but that one is described as an example in the module’s documentation). It also allows new actions to be defined.
Is it possible to manipulate HTTP requests globally in AngularJS? Describe your approach.
Yes, requests can be intercepted, and Angular provides a great api to do that - the “$http” interceptors. “.interceptors” is an array, available at “$httpProvider”, so it can be manipulated from “.config()” blocks. That array should consist of functions which return an object, basically factories.
Unit testing controllers and services - what are the differences?
The main difference between unit testing controllers and services stems from the differences in concerns. Controllers are used for setting the initial state and behavior of the scope they are bound to. We could say that all the models set on scope, either directly or using the //this// keyword, are public. This is still somewhat similar to the public properties of services. Controllers should not contain business logic though.
In unit testing controllers, one could expect more assurances of the initial values of models, and less logic. The logic in controller methods should mostly be just coupling UI actions to services. All functionality that is not tightly bound to the current view and scope, should be delegated to services. The developer would definitely have more spies set on mocked services objects in controller tests than in service tests.
Conversely, the services should be tested primarily for correct business logic handling.
What should be the maximum number of concurrent “watches”? Bonus: How would you keep an eye on that number?
To reduce memory consumption and improve performance it is a good idea to limit the number of watches on a page to 2,000. A utility called ng-stats can help track your watch count and digest cycles.
How do you share data between controllers?
Create an AngularJS service that will hold the data and inject it inside of the controllers.
There are couple of other ways to implement data sharing between controllers, like:
– Using events
– Using $parent, nextSibling, controllerAs, etc. to directly access the controllers
– Using the $rootScope to add the data on (not a good practice)
What is the difference between ng-show/ng-hide and ng-if directives?
ng-show/ng-hide will always insert the DOM element, but will display/hide it based on the condition. ng-if will not insert the DOM element until the condition is not fulfilled.
ng-if is better when we needed the DOM to be loaded conditionally, as it will help load page bit faster compared to ng-show/ng-hide.